FbxTexture is the base class for textures in the FBX SDK. Textures rely on an underlying material to influence how the geometry is rendered. In the following code sample, we associate the diffuse, ambient and emissive channels of a Phong material to three distinct instances of FbxFileTexture. FbxFileTexture represents any texture loaded from a file. For more information on referencing embedded or non-embedded media in files, see Referencing Media.
// Create texture for cube. void CreateTexture(FbxScene* pScene, FbxMesh* pMesh) { // A texture need to be connected to a property on the material, // so let's use the material (if it exists) or create a new one FbxSurfacePhong* lMaterial = NULL; //get the node of mesh, add material for it. FbxNode* lNode = pMesh->GetNode(); if(lNode) { lMaterial = lNode->GetSrcObject<FbxSurfacePhong>(0); if (lMaterial == NULL) { FbxString lMaterialName = "toto"; FbxString lShadingName = "Phong"; FbxDouble3 lBlack(0.0, 0.0, 0.0); FbxDouble3 lRed(1.0, 0.0, 0.0); FbxDouble3 lDiffuseColor(0.75, 0.75, 0.0); lMaterial = FbxSurfacePhong::Create(pScene, lMaterialName.Buffer()); // Generate primary and secondary colors. lMaterial->Emissive .Set(lBlack); lMaterial->Ambient .Set(lRed); lMaterial->AmbientFactor .Set(1.); // Add texture for diffuse channel lMaterial->Diffuse .Set(lDiffuseColor); lMaterial->DiffuseFactor .Set(1.); lMaterial->TransparencyFactor.Set(0.4); lMaterial->ShadingModel .Set(lShadingName); lMaterial->Shininess .Set(0.5); lMaterial->Specular .Set(lBlack); lMaterial->SpecularFactor .Set(0.3); lNode->AddMaterial(lMaterial); } } FbxFileTexture* lTexture = FbxFileTexture::Create(pScene,"Diffuse Texture"); // Set texture properties. lTexture->SetFileName("scene03.jpg"); // Resource file is in current directory. lTexture->SetTextureUse(FbxTexture::eStandard); lTexture->SetMappingType(FbxTexture::eUV); lTexture->SetMaterialUse(FbxFileTexture::eModelMaterial); lTexture->SetSwapUV(false); lTexture->SetTranslation(0.0, 0.0); lTexture->SetScale(1.0, 1.0); lTexture->SetRotation(0.0, 0.0); // don't forget to connect the texture to the corresponding property of the material if (lMaterial) lMaterial->Diffuse.ConnectSrcObject(lTexture); lTexture = FbxFileTexture::Create(pScene,"Ambient Texture"); // Set texture properties. lTexture->SetFileName("gradient.jpg"); // Resource file is in current directory. lTexture->SetTextureUse(FbxTexture::eStandard); lTexture->SetMappingType(FbxTexture::eUV); lTexture->SetMaterialUse(FbxFileTexture::eModelMaterial); lTexture->SetSwapUV(false); lTexture->SetTranslation(0.0, 0.0); lTexture->SetScale(1.0, 1.0); lTexture->SetRotation(0.0, 0.0); // don't forget to connect the texture to the corresponding property of the material if (lMaterial) lMaterial->Ambient.ConnectSrcObject(lTexture); lTexture = FbxFileTexture::Create(pScene,"Emissive Texture"); // Set texture properties. lTexture->SetFileName("spotty.jpg"); // Resource file is in current directory. lTexture->SetTextureUse(FbxTexture::eStandard); lTexture->SetMappingType(FbxTexture::eUV); lTexture->SetMaterialUse(FbxFileTexture::eModelMaterial); lTexture->SetSwapUV(false); lTexture->SetTranslation(0.0, 0.0); lTexture->SetScale(1.0, 1.0); lTexture->SetRotation(0.0, 0.0); // don't forget to connect the texture to the corresponding property of the material if (lMaterial) lMaterial->Emissive.ConnectSrcObject(lTexture); }
The following code sample makes use of the CreateTexture() function we defined above. We first begin by defining the control points and normals of the cube.
// Create a cube with a texture. FbxNode* CreateCubeWithTexture(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, 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); 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 control points. lMesh->InitControlPoints(24); FbxVector4* lControlPoints = lMesh->GetControlPoints(); lControlPoints[0] = vertex0; lControlPoints[1] = vertex1; lControlPoints[2] = vertex2; lControlPoints[3] = vertex3; lControlPoints[4] = vertex1; lControlPoints[5] = vertex5; lControlPoints[6] = vertex6; lControlPoints[7] = vertex2; lControlPoints[8] = vertex5; lControlPoints[9] = vertex4; lControlPoints[10] = vertex7; lControlPoints[11] = vertex6; lControlPoints[12] = vertex4; lControlPoints[13] = vertex0; lControlPoints[14] = vertex3; lControlPoints[15] = vertex7; lControlPoints[16] = vertex3; lControlPoints[17] = vertex2; lControlPoints[18] = vertex6; lControlPoints[19] = vertex7; lControlPoints[20] = vertex1; lControlPoints[21] = vertex0; lControlPoints[22] = vertex4; lControlPoints[23] = vertex5; // We want to have one normal for each vertex (or control point), // so we set the mapping mode to eByControlPoint. FbxGeometryElementNormal* lGeometryElementNormal= lMesh->CreateElementNormal(); lGeometryElementNormal->SetMappingMode(FbxGeometryElement::eByControlPoint); // Here are two different ways to set the normal values. bool firstWayNormalCalculations=true; if (firstWayNormalCalculations) { // The first method is to set the actual normal value // for every control point. lGeometryElementNormal->SetReferenceMode(FbxGeometryElement::eDirect); lGeometryElementNormal->GetDirectArray().Add(lNormalZPos); lGeometryElementNormal->GetDirectArray().Add(lNormalZPos); lGeometryElementNormal->GetDirectArray().Add(lNormalZPos); lGeometryElementNormal->GetDirectArray().Add(lNormalZPos); lGeometryElementNormal->GetDirectArray().Add(lNormalXPos); lGeometryElementNormal->GetDirectArray().Add(lNormalXPos); lGeometryElementNormal->GetDirectArray().Add(lNormalXPos); lGeometryElementNormal->GetDirectArray().Add(lNormalXPos); lGeometryElementNormal->GetDirectArray().Add(lNormalZNeg); lGeometryElementNormal->GetDirectArray().Add(lNormalZNeg); lGeometryElementNormal->GetDirectArray().Add(lNormalZNeg); lGeometryElementNormal->GetDirectArray().Add(lNormalZNeg); lGeometryElementNormal->GetDirectArray().Add(lNormalXNeg); lGeometryElementNormal->GetDirectArray().Add(lNormalXNeg); lGeometryElementNormal->GetDirectArray().Add(lNormalXNeg); lGeometryElementNormal->GetDirectArray().Add(lNormalXNeg); lGeometryElementNormal->GetDirectArray().Add(lNormalYPos); lGeometryElementNormal->GetDirectArray().Add(lNormalYPos); lGeometryElementNormal->GetDirectArray().Add(lNormalYPos); lGeometryElementNormal->GetDirectArray().Add(lNormalYPos); lGeometryElementNormal->GetDirectArray().Add(lNormalYNeg); lGeometryElementNormal->GetDirectArray().Add(lNormalYNeg); lGeometryElementNormal->GetDirectArray().Add(lNormalYNeg); lGeometryElementNormal->GetDirectArray().Add(lNormalYNeg); } else { // The second method is to the possible values of the normals // in the direct array, and set the index of that value // in the index array for every control point. lGeometryElementNormal->SetReferenceMode(FbxGeometryElement::eIndexToDirect); // Add the 6 different normals to the direct array lGeometryElementNormal->GetDirectArray().Add(lNormalZPos); lGeometryElementNormal->GetDirectArray().Add(lNormalXPos); lGeometryElementNormal->GetDirectArray().Add(lNormalZNeg); lGeometryElementNormal->GetDirectArray().Add(lNormalXNeg); lGeometryElementNormal->GetDirectArray().Add(lNormalYPos); lGeometryElementNormal->GetDirectArray().Add(lNormalYNeg); // Now for each control point, we need to specify which normal to use lGeometryElementNormal->GetIndexArray().Add(0); // index of lNormalZPos in the direct array. lGeometryElementNormal->GetIndexArray().Add(0); // index of lNormalZPos in the direct array. lGeometryElementNormal->GetIndexArray().Add(0); // index of lNormalZPos in the direct array. lGeometryElementNormal->GetIndexArray().Add(0); // index of lNormalZPos in the direct array. lGeometryElementNormal->GetIndexArray().Add(1); // index of lNormalXPos in the direct array. lGeometryElementNormal->GetIndexArray().Add(1); // index of lNormalXPos in the direct array. lGeometryElementNormal->GetIndexArray().Add(1); // index of lNormalXPos in the direct array. lGeometryElementNormal->GetIndexArray().Add(1); // index of lNormalXPos in the direct array. lGeometryElementNormal->GetIndexArray().Add(2); // index of lNormalZNeg in the direct array. lGeometryElementNormal->GetIndexArray().Add(2); // index of lNormalZNeg in the direct array. lGeometryElementNormal->GetIndexArray().Add(2); // index of lNormalZNeg in the direct array. lGeometryElementNormal->GetIndexArray().Add(2); // index of lNormalZNeg in the direct array. lGeometryElementNormal->GetIndexArray().Add(3); // index of lNormalXNeg in the direct array. lGeometryElementNormal->GetIndexArray().Add(3); // index of lNormalXNeg in the direct array. lGeometryElementNormal->GetIndexArray().Add(3); // index of lNormalXNeg in the direct array. lGeometryElementNormal->GetIndexArray().Add(3); // index of lNormalXNeg in the direct array. lGeometryElementNormal->GetIndexArray().Add(4); // index of lNormalYPos in the direct array. lGeometryElementNormal->GetIndexArray().Add(4); // index of lNormalYPos in the direct array. lGeometryElementNormal->GetIndexArray().Add(4); // index of lNormalYPos in the direct array. lGeometryElementNormal->GetIndexArray().Add(4); // index of lNormalYPos in the direct array. lGeometryElementNormal->GetIndexArray().Add(5); // index of lNormalYNeg in the direct array. lGeometryElementNormal->GetIndexArray().Add(5); // index of lNormalYNeg in the direct array. lGeometryElementNormal->GetIndexArray().Add(5); // index of lNormalYNeg in the direct array. lGeometryElementNormal->GetIndexArray().Add(5); // index of lNormalYNeg in the direct array. }
We then call FbxMesh::CreateElementUV() to create three new texture layers in the mesh - one for each of the diffuse, ambient, and emissive material channels. The resulting texture layer elements (FbxGeometryElementUV) define how to map the texture's UV coordinates to each of the polygon's vertices. Lastly, we call FbxNode::SetShadingMode() with the value FbxNode::eTextureShading to allow our textures to be rendered in the scene.
// Array of polygon vertices. int lPolygonVertices[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 }; // Create UV for Diffuse channel FbxGeometryElementUV* lUVDiffuseElement = lMesh->CreateElementUV( "DiffuseUV"); K_ASSERT( lUVDiffuseElement != NULL); lUVDiffuseElement->SetMappingMode(FbxGeometryElement::eByPolygonVertex); lUVDiffuseElement->SetReferenceMode(FbxGeometryElement::eIndexToDirect); FbxVector2 lVectors0(0, 0); FbxVector2 lVectors1(1, 0); FbxVector2 lVectors2(1, 1); FbxVector2 lVectors3(0, 1); lUVDiffuseElement->GetDirectArray().Add(lVectors0); lUVDiffuseElement->GetDirectArray().Add(lVectors1); lUVDiffuseElement->GetDirectArray().Add(lVectors2); lUVDiffuseElement->GetDirectArray().Add(lVectors3); // Create UV for Ambient channel FbxGeometryElementUV* lUVAmbientElement = lMesh->CreateElementUV("AmbientUV"); lUVAmbientElement->SetMappingMode(FbxGeometryElement::eByPolygonVertex); lUVAmbientElement->SetReferenceMode(FbxGeometryElement::eIndexToDirect); lVectors0.Set(0, 0); lVectors1.Set(1, 0); lVectors2.Set(0, 0.418586879968643); lVectors3.Set(1, 0.418586879968643); lUVAmbientElement->GetDirectArray().Add(lVectors0); lUVAmbientElement->GetDirectArray().Add(lVectors1); lUVAmbientElement->GetDirectArray().Add(lVectors2); lUVAmbientElement->GetDirectArray().Add(lVectors3); // Create UV for Emissive channel FbxGeometryElementUV* lUVEmissiveElement = lMesh->CreateElementUV("EmissiveUV"); lUVEmissiveElement->SetMappingMode(FbxGeometryElement::eByPolygonVertex); lUVEmissiveElement->SetReferenceMode(FbxGeometryElement::eIndexToDirect); lVectors0.Set(0.2343, 0); lVectors1.Set(1, 0.555); lVectors2.Set(0.333, 0.999); lVectors3.Set(0.555, 0.666); lUVEmissiveElement->GetDirectArray().Add(lVectors0); lUVEmissiveElement->GetDirectArray().Add(lVectors1); lUVEmissiveElement->GetDirectArray().Add(lVectors2); lUVEmissiveElement->GetDirectArray().Add(lVectors3); //Now we have set the UVs as eIndexToDirect reference and in eByPolygonVertex mapping mode //we must update the size of the index array. lUVDiffuseElement->GetIndexArray().SetCount(24); lUVAmbientElement->GetIndexArray().SetCount(24); lUVEmissiveElement->GetIndexArray().SetCount(24); // Create polygons. Assign texture and texture UV indices. for(i = 0; i < 6; i++) { //we won't use the default way of assigning textures, as we have //textures on more than just the default (diffuse) channel. lMesh->BeginPolygon(-1, -1, false); for(j = 0; j < 4; j++) { //this function points lMesh->AddPolygon(lPolygonVertices[i*4 + j] // Control point index. ); //Now we have to update the index array of the UVs for diffuse, ambient and emissive lUVDiffuseElement->GetIndexArray().SetAt(i*4+j, j); lUVAmbientElement->GetIndexArray().SetAt(i*4+j, j); lUVEmissiveElement->GetIndexArray().SetAt(i*4+j, j); } lMesh->EndPolygon (); } FbxNode* lNode = FbxNode::Create(pScene,pName); lNode->SetNodeAttribute(lMesh); lNode->SetShadingMode(FbxNode::eTextureShading); CreateTexture(pScene, lMesh); return lNode; }