Meshes

Creating a Mesh

Meshes in the FBX SDK are abstracted by the FbxMesh class. A mesh is defined by a set of per-face vertices, or "control points", and by a group of layers to define the mesh's normals, textures, and materials. The following code sample illustrates how to instantiate a FbxMesh.

// Create a node for our mesh in the scene.
FbxNode* lMeshNode = FbxNode::Create(pScene, "meshNode");

// Create a mesh.
FbxMesh* lMesh = FbxMesh::Create(pScene, "mesh");

// Set the node attribute of the mesh node.
lMeshNode->SetNodeAttribute(lMesh);

// Add the mesh node to the root node in the scene.
FbxNode *lRootNode = pScene->GetRootNode();
lRootNode->AddChild(lMeshNode);

Defining Control Points

The per-face vertices of a FbxMesh are known as control points. Since objects in the FBX SDK are created by default in the right handed, Y-Up axis system, the vertices of a mesh should be defined accordingly. An instance of FbxMesh contains an array of control points which can be initialized to a specific size. For example, a cube's mesh requires 24 control points: there are 4 control points per face, and a cube has 6 faces. The following code sample initializes the array of control points for a cube.

// Define the eight corners of the cube.
// The cube spans from
//    -50 to  50 along the X axis
//      0 to 100 along the Y axis
//    -50 to  50 along the Z axis
FbxVector4 vertex0(-50, 0, 50);
FbxVector4 vertex1(50, 0, 50);
FbxVector4 vertex2(50, 100, 50);
FbxVector4 vertex3(-50, 100, 50);
FbxVector4 vertex4(-50, 0, -50);
FbxVector4 vertex5(50, 0, -50);
FbxVector4 vertex6(50, 100, -50);
FbxVector4 vertex7(-50, 100, -50);

// Initialize the control point array of the mesh.
lMesh->InitControlPoints(24);
FbxVector4* lControlPoints = lMesh->GetControlPoints();

// Define each face of the cube.
// Face 1
lControlPoints[0] = vertex0;
lControlPoints[1] = vertex1;
lControlPoints[2] = vertex2;
lControlPoints[3] = vertex3;
// Face 2
lControlPoints[4] = vertex1;
lControlPoints[5] = vertex5;
lControlPoints[6] = vertex6;
lControlPoints[7] = vertex2;
// Face 3
lControlPoints[8] = vertex5;
lControlPoints[9] = vertex4;
lControlPoints[10] = vertex7;
lControlPoints[11] = vertex6;
// Face 4
lControlPoints[12] = vertex4;
lControlPoints[13] = vertex0;
lControlPoints[14] = vertex3;
lControlPoints[15] = vertex7;
// Face 5
lControlPoints[16] = vertex3;
lControlPoints[17] = vertex2;
lControlPoints[18] = vertex6;
lControlPoints[19] = vertex7;
// Face 6
lControlPoints[20] = vertex1;
lControlPoints[21] = vertex0;
lControlPoints[22] = vertex4;
lControlPoints[23] = vertex5;

For more information on control point management, consult the FbxGeometry class documentation. FbxGeometry is the parent class of FbxMesh, FbxLine, FbxNurb and other classes used to define scene geometry.

NOTE:Note that a scene axis conversion does not affect the vertex values of a mesh. For more information, see Scene Axis and Unit Conversion.

Assigning Normals

The normal vectors of a mesh are defined in an instance of FbxLayerElementNormal. Layer elements such as normals can be mapped to the surface of a mesh in a variety of ways, such as by control point (FbxLayerElement::eByControlPoint), by polygon vertex (FbxLayerElement::eByPolygonVertex), by polygon (FbxLayerElement::eByPolygon), by edge (FbxLayerElement::eByEdge), or one mapping coordinate for the whole surface (FbxLayerElement::eAllSame). For more information, see FbxLayerElement::EMappingMode.

Given an array of normal vectors and an array of control points, we can specify how the array of normal vectors is referenced by the array of control points. This is defined by the FbxLayerElement::EReferenceMode assigned in FbxLayerElement::SetReferenceMode(). The EReferenceMode::eDirect mode maps the n'th element in the normal vector array to the n'th element in the control point array.

Reference Mode (FbxLayerElement::EReferenceMode) Description
FbxLayerElement::eDirect This indicates that the mapping information for the n'th element is found in the n'th place of FbxLayerElementTemplate::mDirectArray.
FbxLayerElement::eIndex This symbol is kept for backward compatibility with FBX v5.0 files. In FBX v6.0 and higher, this symbol is replaced with FbxLayerElement::eIndexToDirect.
FbxLayerElement::eIndexToDirect This indicates that each element of FbxLayerElementTemplate::mIndexArray contains an index referring to an element in FbxLayerElementTemplate::mDirectArray.

In the following code sample, we will examine how to apply a per-control point mapping (FbxLayerElement::eByControlPoint) of normals onto a mesh using a EReferenceMode::eDirect reference mode. Observe that the order in which FbxLayerElementArrayTemplate::Add() is invoked corresponds to the order of the control points which have been defined above.

// Define normal vectors along each axis.
FbxVector4 lNormalXPos( 1,  0,  0);
FbxVector4 lNormalXNeg(-1,  0,  0);
FbxVector4 lNormalYPos( 0,  1,  0);
FbxVector4 lNormalYNeg( 0, -1,  0);
FbxVector4 lNormalZPos( 0,  0,  1);
FbxVector4 lNormalZNeg( 0,  0, -1);

// Create layer 0 for the mesh if it does not already exist.
// This is where we will define our normals.
FbxLayer lLayer = lMesh->GetLayer(0);
if(lLayer == NULL) {
    lMesh->CreateLayer();
    lLayer = lMesh->GetLayer(0);
}

// Create a normal layer.
FbxLayerElementNormal* lLayerElementNormal= FbxLayerElementNormal::Create(lMesh, "");

// Set its mapping mode to map each normal vector to each control point.
lLayerElementNormal->SetMappingMode(FbxLayerElement::eByControlPoint);
 
// Set the reference mode of so that the n'th element of the normal array maps to the n'th
// element of the control point array.
lLayerElementNormal->SetReferenceMode(FbxLayerElement::eDirect);

// Assign the normal vectors in the same order the control points were defined for the mesh.
// Face 1
lLayerElementNormal->GetDirectArray().Add(lNormalZPos);
lLayerElementNormal->GetDirectArray().Add(lNormalZPos);
lLayerElementNormal->GetDirectArray().Add(lNormalZPos);
lLayerElementNormal->GetDirectArray().Add(lNormalZPos);
// Face 2
lLayerElementNormal->GetDirectArray().Add(lNormalXPos);
lLayerElementNormal->GetDirectArray().Add(lNormalXPos);
lLayerElementNormal->GetDirectArray().Add(lNormalXPos);
lLayerElementNormal->GetDirectArray().Add(lNormalXPos);
// Face 3
lLayerElementNormal->GetDirectArray().Add(lNormalZNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalZNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalZNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalZNeg);
// Face 4
lLayerElementNormal->GetDirectArray().Add(lNormalXNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalXNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalXNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalXNeg);
// Face 5
lLayerElementNormal->GetDirectArray().Add(lNormalYPos);
lLayerElementNormal->GetDirectArray().Add(lNormalYPos);
lLayerElementNormal->GetDirectArray().Add(lNormalYPos);
lLayerElementNormal->GetDirectArray().Add(lNormalYPos);
// Face 6
lLayerElementNormal->GetDirectArray().Add(lNormalYNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalYNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalYNeg);
lLayerElementNormal->GetDirectArray().Add(lNormalYNeg);

// Finally, we set layer 0 of the mesh to the normal layer element.
lLayer->SetNormals(lLayerElementNormal);