Meshes
 
 
 

Creating a Mesh

Meshes in the FBX SDK are abstracted by the KFbxMesh class. A mesh is defined by a set of 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 KFbxMesh.

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

// Create a mesh.
KFbxMesh* lMesh = KFbxMesh::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.
KFbxNode *lRootNode = pScene->GetRootNode();
lRootNode->AddChild(lMeshNode);

Defining Control Points

The vertices of a KFbxMesh 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 KFbxMesh contains an array of control points which can be initiated 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 100x100x100 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
KFbxVector4 lControlPoint0(-50, 0, 50);
KFbxVector4 lControlPoint1(50, 0, 50);
KFbxVector4 lControlPoint2(50, 100, 50);
KFbxVector4 lControlPoint3(-50, 100, 50);
KFbxVector4 lControlPoint4(-50, 0, -50);
KFbxVector4 lControlPoint5(50, 0, -50);
KFbxVector4 lControlPoint6(50, 100, -50);
KFbxVector4 lControlPoint7(-50, 100, -50);

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

// Define each face of the cube.
// Face 1
lControlPoints[0] = lControlPoint0;
lControlPoints[1] = lControlPoint1;
lControlPoints[2] = lControlPoint2;
lControlPoints[3] = lControlPoint3;
// Face 2
lControlPoints[4] = lControlPoint1;
lControlPoints[5] = lControlPoint5;
lControlPoints[6] = lControlPoint6;
lControlPoints[7] = lControlPoint2;
// Face 3
lControlPoints[8] = lControlPoint5;
lControlPoints[9] = lControlPoint4;
lControlPoints[10] = lControlPoint7;
lControlPoints[11] = lControlPoint6;
// Face 4
lControlPoints[12] = lControlPoint4;
lControlPoints[13] = lControlPoint0;
lControlPoints[14] = lControlPoint3;
lControlPoints[15] = lControlPoint7;
// Face 5
lControlPoints[16] = lControlPoint3;
lControlPoints[17] = lControlPoint2;
lControlPoints[18] = lControlPoint6;
lControlPoints[19] = lControlPoint7;
// Face 6
lControlPoints[20] = lControlPoint1;
lControlPoints[21] = lControlPoint0;
lControlPoints[22] = lControlPoint4;
lControlPoints[23] = lControlPoint5;

For more information on control point management, consult the KFbxGeometry class documentation. KFbxGeometry is the parent class of KFbxMesh, KFbxLine, KFbxNurb and other classes used to define scene geometry.

NoteNote 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 KFbxLayerElementNormal. Layer elements such as normals can be mapped to the surface of a mesh in a variety of ways, such as by control point (KFbxLayerElement::eBY_CONTROL_POINT), by polygon vertex (KFbxLayerElement::eBY_POLYGON_VERTEX), by polygon (KFbxLayerElement::eBY_POLYGON), by edge (KFbxLayerElement::eBY_EDGE), or one mapping coordinate for the whole surface (KFbxLayerElement::eALL_SAME). For more information, see KFbxLayerElement::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 KFbxLayerElement::EReferenceMode assigned in KFbxLayerElement::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 (KFbxLayerElement::EReferenceMode) Description
KFbxLayerElement::eDIRECT This indicates that the mapping information for the n'th element is found in the n'th place of KFbxLayerElementTemplate::mDirectArray.
KFbxLayerElement::eINDEX This symbol is kept for backward compatibility with FBX v5.0 files. In FBX v6.0 and higher, this symbol is replaced with KFbxLayerElement::eINDEX_TO_DIRECT.
KFbxLayerElement::eINDEX_TO_DIRECT This indicates that each element of KFbxLayerElementTemplate::mIndexArray contains an index referring to an element in KFbxLayerElementTemplate::mDirectArray.

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

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

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

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

// Set its mapping mode to map each normal vector to each control point.
lLayerElementNormal->SetMappingMode(KFbxLayerElement::eBY_CONTROL_POINT);
 
// 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(KFbxLayerElement::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);