void getMaterialAndTextureFileNames(FbxGeometry* fbxGeometry, std::vector<std::string>* out_textureFileNames, Material* out_material) { if (fbxGeometry->GetNode() == nullptr) { return; } int numMaterials = fbxGeometry->GetNode()->GetSrcObjectCount(FbxSurfaceMaterial::ClassId); for (int midx = 0; midx < numMaterials; ++midx){ FbxSurfaceMaterial *fbxMaterial = (FbxSurfaceMaterial *)fbxGeometry->GetNode()->GetSrcObject(FbxSurfaceMaterial::ClassId, midx); if (fbxMaterial) { getMaterialData(fbxMaterial, out_material); // Go through all the possible textures int tidx; FBXSDK_FOR_EACH_TEXTURE(tidx) { FbxProperty fbxTextureProperty = fbxMaterial->FindProperty(FbxLayerElement::sTextureChannelNames[tidx]); std::vector<std::string>* tempTextureFileNames = findAndGetTextureInfoByProperty(fbxTextureProperty, midx); for (int t = 0; t < tempTextureFileNames->size(); ++t) { out_textureFileNames->push_back(tempTextureFileNames->at(t)); } } }//end if(fbxMaterial) }// end for materialIndex return; }
void FBXMesh::Builder::unloadCacheRecursive(FbxNode * pNode) { // Unload the material cache const int lMaterialCount = pNode->GetMaterialCount(); for (int lMaterialIndex = 0; lMaterialIndex < lMaterialCount; ++lMaterialIndex) { FbxSurfaceMaterial * lMaterial = pNode->GetMaterial(lMaterialIndex); if (lMaterial && lMaterial->GetUserDataPtr()) { FBXMaterialCache* lMaterialCache = static_cast<FBXMaterialCache*>(lMaterial->GetUserDataPtr()); lMaterial->SetUserDataPtr(NULL); delete lMaterialCache; } } FbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute(); if (lNodeAttribute) { // Unload the mesh cache if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh) { FbxMesh * lMesh = pNode->GetMesh(); if (lMesh && lMesh->GetUserDataPtr()) { #ifndef USE_META_DATA VBOMesh * lMeshCache = static_cast<VBOMesh *>(lMesh->GetUserDataPtr()); lMesh->SetUserDataPtr(NULL); delete lMeshCache; #else FbxMetaData * fbxMetaData = static_cast<FbxMetaData*>(lMesh->GetUserDataPtr()); lMesh->SetUserDataPtr(NULL); delete fbxMetaData; #endif } } // Unload the light cache else if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eLight) { FbxLight * lLight = pNode->GetLight(); if (lLight && lLight->GetUserDataPtr()) { FBXLightCache* lLightCache = static_cast<FBXLightCache*>(lLight->GetUserDataPtr()); lLight->SetUserDataPtr(NULL); delete lLightCache; } } } const int lChildCount = pNode->GetChildCount(); for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) { unloadCacheRecursive(pNode->GetChild(lChildIndex)); } }
void MaterialHandler::MapMaterials(FbxNode * pNode, SceneMap * sceneMap) { //Recursively extract the children for (int j = 0; j < pNode->GetChildCount(); j++) MapMaterials(pNode->GetChild(j), sceneMap); FbxGeometry* pGeometry = pNode->GetGeometry(); int materialCount = 0; FbxNode* node = NULL; if (pGeometry) { node = pGeometry->GetNode(); if (node) materialCount = pNode->GetMaterialCount(); if (materialCount > 0) { for (int i = 0; i < materialCount; i++) { if (pNode->GetMaterial(i)) { FbxSurfaceMaterial *pMaterial = node->GetMaterial(i); std::cout << pMaterial->GetName() << "\n"; if (sceneMap->materialHash.find(pMaterial->GetName()) == sceneMap->materialHash.end()) { // not found std::cout << "New material found! mapping..\n"; sceneMap->materialHash[pMaterial->GetName()] = sceneMap->materialID; sceneMap->materialID += 1; } else { // found std::cout << "Material " << pMaterial->GetName() << " already exist .. skipping mapping of material" << std::endl; } //ProcessData(pMaterial, materialCount, outputMat); } } } } }
// Bake node attributes and materials under this node recursively. // Currently only mesh, light and material. void LoadCacheRecursive(SceneContext* pSceneCtx, FbxNode * pNode, FbxAnimLayer * pAnimLayer, bool pSupportVBO) { // Bake material and hook as user data. const int lMaterialCount = pNode->GetMaterialCount(); for (int lMaterialIndex = 0; lMaterialIndex < lMaterialCount; ++lMaterialIndex) { FbxSurfaceMaterial * lMaterial = pNode->GetMaterial(lMaterialIndex); if (lMaterial && !lMaterial->GetUserDataPtr()) { FbxAutoPtr<MaterialCache> lMaterialCache(new MaterialCache); if (lMaterialCache->Initialize(lMaterial)) { lMaterial->SetUserDataPtr(lMaterialCache.Release()); } } } FbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute(); if (lNodeAttribute) { // Bake mesh as VBO(vertex buffer object) into GPU. if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh) { FbxMesh * lMesh = pNode->GetMesh(); if (pSupportVBO && lMesh && !lMesh->GetUserDataPtr()) { FbxAutoPtr<VBOMesh> lMeshCache(new VBOMesh); if (lMeshCache->Initialize(pSceneCtx, lMesh)) { lMesh->SetUserDataPtr(lMeshCache.Release()); } } } // Bake light properties. else if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eLight) { FbxLight * lLight = pNode->GetLight(); if (lLight && !lLight->GetUserDataPtr()) { FbxAutoPtr<LightCache> lLightCache(new LightCache); if (lLightCache->Initialize(lLight, pAnimLayer)) { lLight->SetUserDataPtr(lLightCache.Release()); } } } } const int lChildCount = pNode->GetChildCount(); for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) { LoadCacheRecursive(pSceneCtx, pNode->GetChild(lChildIndex), pAnimLayer, pSupportVBO); } }
reMaterial* reFBXAsset::getMaterial( FbxMesh* fmesh, int i, reMaterialSet& set) { reMaterial* mat = NULL; for (int l = 0; l < fmesh->GetElementMaterialCount(); l++) { FbxGeometryElementMaterial* lMaterialElement = fmesh->GetElementMaterial(l); int lMatId = lMaterialElement->GetIndexArray().GetAt(i); if(lMatId >= 0) { if (mat = set.materialById(lMatId)) return mat; mat = new reMaterial; mat->id = lMatId; set.addMetarial(mat); FbxSurfaceMaterial* lMaterial = fmesh->GetNode()->GetMaterial(lMaterialElement->GetIndexArray().GetAt(i)); if (!lMaterial) { continue; } ////////////////////////////////////////////////////////////////////////// FbxProperty lProperty = lMaterial->FindProperty(FbxSurfaceMaterial::sDiffuse); if (lMaterial->GetClassId().Is(FbxSurfacePhong::ClassId)) { FbxDouble3 lFbxDouble3; lFbxDouble3 =((FbxSurfacePhong *)lMaterial)->Diffuse; mat->diffuseColor = reColor4(lFbxDouble3[0], lFbxDouble3[1], lFbxDouble3[2], 1); } if (lMaterial->GetClassId().Is(FbxSurfaceLambert::ClassId)) { FbxDouble3 lFbxDouble3; lFbxDouble3 =((FbxSurfaceLambert *)lMaterial)->Diffuse; mat->diffuseColor = reColor4(lFbxDouble3[0], lFbxDouble3[1], lFbxDouble3[2], 1); } ////////////////////////////////////////////////////////////////////////// read texture int lNbTextures = lProperty.GetSrcObjectCount(FbxTexture::ClassId); if (lNbTextures) { mat->diffuseTexture = new reTexture; FbxTexture* lTexture = FbxCast <FbxTexture> (lProperty.GetSrcObject(FbxTexture::ClassId,0)); qDebug() << "map: " << lTexture->GetName(); FbxFileTexture *lFileTexture = FbxCast<FbxFileTexture>(lTexture); if (lFileTexture) { mat->diffuseTexture->fileName(lFileTexture->GetFileName()); } } ////////////////////////////////////////////////////////////////////////// } } return mat; }
void FBXSceneEncoder::loadMaterial(FbxNode* fbxNode) { Node* node = findNode(fbxNode); Model* model = (node) ? node->getModel() : NULL; const int materialCount = fbxNode->GetMaterialCount(); for (int index = 0; index < materialCount; ++index) { FbxSurfaceMaterial* fbxMaterial = fbxNode->GetMaterial(index); string materialName(fbxMaterial->GetName()); fixMaterialName(materialName); Material* material = NULL; map<string, Material*>::iterator it = _materials.find(materialName); if (it != _materials.end()) { // This material was already loaded so don't load it again material = it->second; } else { if (EncoderArguments::getInstance()->outputMaterialEnabled()) { material = createMaterial(materialName, fbxMaterial, node); } else { // If outputMaterialEnabled() is not enabled then only create the materials for the purpose of writing // the material name in the GPB file. There is no need to load uniforms and samplers for the material. material = new Material(materialName); } _materials[materialName] = material; } if (materialCount == 1 && material && model) { model->setMaterial(material); // TODO: add support for materials per mesh part } else if (materialCount > 1 && material && model) { model->setMaterial(material, index); } } const int childCount = fbxNode->GetChildCount(); for (int i = 0; i < childCount; ++i) { FbxNode* childNode = fbxNode->GetChild(i); if (childNode) { loadMaterial(childNode); } } }
void FbxLoader::BindMaterial(FbxNode* node, Node& meshNode) { const int materialCount = node->GetMaterialCount(); meshNode.materialNames.resize(materialCount); for(int i = 0; i < materialCount; i++) { FbxSurfaceMaterial* surfaceMaterial = node->GetMaterial(i); auto name = surfaceMaterial->GetName(); meshNode.materialNames[i] = name; if(materials[name].normalMapName != "") meshNode.useNormalMap = true; } }
void Converter::getMaterials(FbxNode *n, std::vector<std::string> &textures, std::vector<PhongMaterial> &phongMats, std::vector<LambertMaterial> &lambertMats) { for (int i = 0; i < n->GetMaterialCount(); ++i) { FbxSurfaceMaterial *material = n->GetMaterial(i); getDiffuseTextures(material, textures); if (material->GetClassId().Is(FbxSurfacePhong::ClassId)) { phongMats.push_back(getPhongMaterial(material)); } else if (material->GetClassId().Is(FbxSurfaceLambert::ClassId)) { lambertMats.push_back(getLambertMaterial(material)); } } }
void LoadMeshes(FbxNode* pFbxNode, packed_freelist<Mesh>& sceneMeshes) { // Material const uint32_t materialCount = pFbxNode->GetMaterialCount(); for (uint32_t i = 0; i < materialCount; ++i) { FbxSurfaceMaterial* pFbxMaterial = pFbxNode->GetMaterial(i); if (pFbxMaterial && !pFbxMaterial->GetUserDataPtr()) { FbxAutoPtr<Material> pMaterial(new Material); if (pMaterial->init(pFbxMaterial)) { pFbxMaterial->SetUserDataPtr(pMaterial.Release()); } } } FbxNodeAttribute* nodeAttribute = pFbxNode->GetNodeAttribute(); if (nodeAttribute) { // Mesh if (nodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh) { FbxMesh* pFbxMesh = pFbxNode->GetMesh(); if (pFbxMesh && !pFbxMesh->GetUserDataPtr()) { Mesh mesh; if (mesh.init(pFbxMesh)) { sceneMeshes.insert(mesh); } // TODO: FbxAutoPtr<Mesh> pMesh(new Mesh); if (pMesh->init(pFbxMesh)) { pFbxMesh->SetUserDataPtr(pMesh.Release()); } } } // Light else if (nodeAttribute->GetAttributeType() == FbxNodeAttribute::eLight) { FbxLight* pFbxLight = pFbxNode->GetLight(); if (pFbxLight && !pFbxLight->GetUserDataPtr()) { FbxAutoPtr<Light> pLight(new Light); if (pLight->init(pFbxLight)) { pFbxLight->SetUserDataPtr(pLight.Release()); } } } } const int childCount = pFbxNode->GetChildCount(); for (int i = 0; i < childCount; ++i) { LoadMeshes(pFbxNode->GetChild(i), sceneMeshes); } }
// Unload the cache and release the memory under this node recursively. void UnloadCacheRecursive(FbxNode * pNode) { // Unload the material cache const int lMaterialCount = pNode->GetMaterialCount(); for (int lMaterialIndex = 0; lMaterialIndex < lMaterialCount; ++lMaterialIndex) { FbxSurfaceMaterial * lMaterial = pNode->GetMaterial(lMaterialIndex); if (lMaterial && lMaterial->GetUserDataPtr()) { MaterialCache * lMaterialCache = static_cast<MaterialCache *>(lMaterial->GetUserDataPtr()); lMaterial->SetUserDataPtr(NULL); delete lMaterialCache; } } FbxNodeAttribute* lNodeAttribute = pNode->GetNodeAttribute(); if (lNodeAttribute) { // Unload the mesh cache if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh) { FbxMesh * lMesh = pNode->GetMesh(); if (lMesh && lMesh->GetUserDataPtr()) { VBOMesh * lMeshCache = static_cast<VBOMesh *>(lMesh->GetUserDataPtr()); lMesh->SetUserDataPtr(NULL); delete lMeshCache; } } // Unload the light cache else if (lNodeAttribute->GetAttributeType() == FbxNodeAttribute::eLight) { FbxLight * lLight = pNode->GetLight(); if (lLight && lLight->GetUserDataPtr()) { LightCache * lLightCache = static_cast<LightCache *>(lLight->GetUserDataPtr()); lLight->SetUserDataPtr(NULL); delete lLightCache; } } } const int lChildCount = pNode->GetChildCount(); for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) { UnloadCacheRecursive(pNode->GetChild(lChildIndex)); } }
//------------------------------------------------------------------------- // //------------------------------------------------------------------------- void UnFbx::FFbxImporter::FixupMaterial( FbxSurfaceMaterial& FbxMaterial, UMaterial* UnrealMaterial ) { // add a basic diffuse color if no texture is linked to diffuse if (UnrealMaterial->BaseColor.Expression == NULL) { FbxDouble3 DiffuseColor; UMaterialExpressionVectorParameter* MyColorExpression = ConstructObject<UMaterialExpressionVectorParameter>( UMaterialExpressionVectorParameter::StaticClass(), UnrealMaterial ); UnrealMaterial->Expressions.Add( MyColorExpression ); UnrealMaterial->BaseColor.Expression = MyColorExpression; bool bFoundDiffuseColor = true; if( FbxMaterial.GetClassId().Is(FbxSurfacePhong::ClassId) ) { DiffuseColor = ((FbxSurfacePhong&)(FbxMaterial)).Diffuse.Get(); } else if( FbxMaterial.GetClassId().Is(FbxSurfaceLambert::ClassId) ) { DiffuseColor = ((FbxSurfaceLambert&)(FbxMaterial)).Diffuse.Get(); } else { bFoundDiffuseColor = false; } if( bFoundDiffuseColor ) { MyColorExpression->DefaultValue.R = (float)(DiffuseColor[0]); MyColorExpression->DefaultValue.G = (float)(DiffuseColor[1]); MyColorExpression->DefaultValue.B = (float)(DiffuseColor[2]); } else { // use random color because there may be multiple materials, then they can be different MyColorExpression->DefaultValue.R = 0.5f+(0.5f*FMath::Rand())/RAND_MAX; MyColorExpression->DefaultValue.G = 0.5f+(0.5f*FMath::Rand())/RAND_MAX; MyColorExpression->DefaultValue.B = 0.5f+(0.5f*FMath::Rand())/RAND_MAX; } TArray<FExpressionOutput> Outputs = UnrealMaterial->BaseColor.Expression->GetOutputs(); FExpressionOutput* Output = Outputs.GetTypedData(); UnrealMaterial->BaseColor.Mask = Output->Mask; UnrealMaterial->BaseColor.MaskR = Output->MaskR; UnrealMaterial->BaseColor.MaskG = Output->MaskG; UnrealMaterial->BaseColor.MaskB = Output->MaskB; UnrealMaterial->BaseColor.MaskA = Output->MaskA; } }
void FBXImporter::LoadMaterialAttributes(FBXMeshData* fbxMeshData) { // Get the name of material. FbxSurfaceMaterial* surfaceMaterial = fbxMeshData->mSurfaceMaterial; const char* materialName = surfaceMaterial->GetName(); // Phong material if (surfaceMaterial->GetClassId().Is(FbxSurfacePhong::ClassId)) { // Ambient color. FbxDouble3 ambient = ((FbxSurfacePhong*)surfaceMaterial)->Ambient; // Diffuse color. FbxDouble3 diffuse = ((FbxSurfacePhong*)surfaceMaterial)->Diffuse; // Specular color. FbxDouble3 specular = ((FbxSurfacePhong*)surfaceMaterial)->Specular; // Emissive color. FbxDouble3 emissive = ((FbxSurfacePhong*)surfaceMaterial)->Emissive; // Opacity. FbxDouble opacity = ((FbxSurfacePhong*)surfaceMaterial)->TransparencyFactor; // Shininess. FbxDouble shininess = ((FbxSurfacePhong*)surfaceMaterial)->Shininess; // Reflectivety. FbxDouble reflectiveity = ((FbxSurfacePhong*)surfaceMaterial)->ReflectionFactor; } // Lambert material. if (surfaceMaterial->GetClassId().Is(FbxSurfaceLambert::ClassId)) { // Ambient color. FbxDouble3 ambient = ((FbxSurfaceLambert*)surfaceMaterial)->Ambient; // Diffuse color. FbxDouble3 diffuse = ((FbxSurfaceLambert*)surfaceMaterial)->Diffuse; // Emissive color. FbxDouble3 emissive = ((FbxSurfaceLambert*)surfaceMaterial)->Emissive; // Opacity. FbxDouble opacity = ((FbxSurfaceLambert*)surfaceMaterial)->TransparencyFactor; } }
//------------------------------------------------------------------------------------------------------------------------------------------- void transferTextures(FbxGeometry* fbxMesh, Mesh* mesh) { FbxNode* fbxNode = fbxMesh->GetNode(); FbxProperty fbxProperty; int numMaterials = fbxNode->GetSrcObjectCount<FbxSurfaceMaterial>(); for (int matId = 0; matId < numMaterials; matId++){ FbxSurfaceMaterial* fbxMaterial = fbxNode->GetSrcObject<FbxSurfaceMaterial>(matId); Material* modelMaterial = mesh->Materials[matId]; if (fbxMaterial){ // Go through all the possible textures for (int layerId = 0; layerId < FbxLayerElement::sTypeTextureCount; layerId++){ fbxProperty = fbxMaterial->FindProperty(FbxLayerElement::sTextureChannelNames[layerId]); transferTextureByProperty(fbxProperty, matId, modelMaterial); } } } LOG_DEBUG << "Transfer materials successfully! "; }
void FbxUtil::LoadMaterial(const SceneNode::Ptr &ntNode, FbxNode *fbxNode) { if (fbxNode->GetMaterialCount() > 0) { FbxSurfaceMaterial *fbxMaterial = fbxNode->GetMaterial(0); // only supports phong material if (fbxMaterial->GetClassId().Is(FbxSurfacePhong::ClassId)) { Material::Ptr material = EntityUtil::Instance()->FindEntity<Material>(fbxMaterial->GetName()); if (material == nullptr) { material = CreateMaterial(fbxMaterial); EntityUtil::Instance()->AddEntity(material); } if (auto ptr = ntNode->GetComponent<MeshRender>()) ptr->SetMaterial(material); } } }
//converts a FBX mesh to a CC mesh static ccMesh* FromFbxMesh(FbxMesh* fbxMesh, FileIOFilter::LoadParameters& parameters) { if (!fbxMesh) return 0; int polyCount = fbxMesh->GetPolygonCount(); //fbxMesh->GetLayer( unsigned triCount = 0; unsigned polyVertCount = 0; //different from vertCount (vertices can be counted multiple times here!) //as we can't load all polygons (yet ;) we already look if we can load any! { unsigned skipped = 0; for (int i=0; i<polyCount; ++i) { int pSize = fbxMesh->GetPolygonSize(i); if (pSize == 3) { ++triCount; polyVertCount += 3; } else if (pSize == 4) { triCount += 2; polyVertCount += 4; } else { ++skipped; } } if (triCount == 0) { ccLog::Warning(QString("[FBX] No triangle or quad found in mesh '%1'! (polygons with more than 4 vertices are not supported for the moment)").arg(fbxMesh->GetName())); return 0; } else if (skipped != 0) { ccLog::Warning(QString("[FBX] Some polygons in mesh '%1' were ignored (%2): polygons with more than 4 vertices are not supported for the moment)").arg(fbxMesh->GetName()).arg(skipped)); return 0; } } int vertCount = fbxMesh->GetControlPointsCount(); if (vertCount <= 0) { ccLog::Warning(QString("[FBX] Mesh '%1' has no vetex or no polygon?!").arg(fbxMesh->GetName())); return 0; } ccPointCloud* vertices = new ccPointCloud("vertices"); ccMesh* mesh = new ccMesh(vertices); mesh->setName(fbxMesh->GetName()); mesh->addChild(vertices); vertices->setEnabled(false); if (!mesh->reserve(static_cast<unsigned>(triCount)) || !vertices->reserve(vertCount)) { ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1'!").arg(fbxMesh->GetName())); delete mesh; return 0; } //colors { for (int l=0; l<fbxMesh->GetElementVertexColorCount(); l++) { FbxGeometryElementVertexColor* vertColor = fbxMesh->GetElementVertexColor(l); //CC can only handle per-vertex colors if (vertColor->GetMappingMode() == FbxGeometryElement::eByControlPoint) { if (vertColor->GetReferenceMode() == FbxGeometryElement::eDirect || vertColor->GetReferenceMode() == FbxGeometryElement::eIndexToDirect) { if (vertices->reserveTheRGBTable()) { switch (vertColor->GetReferenceMode()) { case FbxGeometryElement::eDirect: { for (int i=0; i<vertCount; ++i) { FbxColor c = vertColor->GetDirectArray().GetAt(i); vertices->addRGBColor( static_cast<colorType>(c.mRed * ccColor::MAX), static_cast<colorType>(c.mGreen * ccColor::MAX), static_cast<colorType>(c.mBlue * ccColor::MAX) ); } } break; case FbxGeometryElement::eIndexToDirect: { for (int i=0; i<vertCount; ++i) { int id = vertColor->GetIndexArray().GetAt(i); FbxColor c = vertColor->GetDirectArray().GetAt(id); vertices->addRGBColor( static_cast<colorType>(c.mRed * ccColor::MAX), static_cast<colorType>(c.mGreen * ccColor::MAX), static_cast<colorType>(c.mBlue * ccColor::MAX) ); } } break; default: assert(false); break; } vertices->showColors(true); mesh->showColors(true); break; //no need to look for other color fields (we won't be able to handle them! } else { ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' colors!").arg(fbxMesh->GetName())); } } else { ccLog::Warning(QString("[FBX] Color field #%i of mesh '%1' will be ignored (unhandled type)").arg(l).arg(fbxMesh->GetName())); } } else { ccLog::Warning(QString("[FBX] Color field #%i of mesh '%1' will be ignored (unhandled type)").arg(l).arg(fbxMesh->GetName())); } } } //normals can be per vertices or per-triangle int perPointNormals = -1; int perVertexNormals = -1; int perPolygonNormals = -1; { for (int j=0; j<fbxMesh->GetElementNormalCount(); j++) { FbxGeometryElementNormal* leNormals = fbxMesh->GetElementNormal(j); switch(leNormals->GetMappingMode()) { case FbxGeometryElement::eByControlPoint: perPointNormals = j; break; case FbxGeometryElement::eByPolygonVertex: perVertexNormals = j; break; case FbxGeometryElement::eByPolygon: perPolygonNormals = j; break; default: //not handled break; } } } //per-point normals if (perPointNormals >= 0) { FbxGeometryElementNormal* leNormals = fbxMesh->GetElementNormal(perPointNormals); FbxLayerElement::EReferenceMode refMode = leNormals->GetReferenceMode(); const FbxLayerElementArrayTemplate<FbxVector4>& normals = leNormals->GetDirectArray(); assert(normals.GetCount() == vertCount); if (normals.GetCount() != vertCount) { ccLog::Warning(QString("[FBX] Wrong number of normals on mesh '%1'!").arg(fbxMesh->GetName())); perPointNormals = -1; } else if (!vertices->reserveTheNormsTable()) { ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' normals!").arg(fbxMesh->GetName())); perPointNormals = -1; } else { //import normals for (int i=0; i<vertCount; ++i) { int id = refMode != FbxGeometryElement::eDirect ? leNormals->GetIndexArray().GetAt(i) : i; FbxVector4 N = normals.GetAt(id); //convert to CC-structure CCVector3 Npc( static_cast<PointCoordinateType>(N.Buffer()[0]), static_cast<PointCoordinateType>(N.Buffer()[1]), static_cast<PointCoordinateType>(N.Buffer()[2]) ); vertices->addNorm(Npc); } vertices->showNormals(true); mesh->showNormals(true); //no need to import the other normals (if any) perVertexNormals = -1; perPolygonNormals = -1; } } //per-triangle normals NormsIndexesTableType* normsTable = 0; if (perVertexNormals >= 0 || perPolygonNormals >= 0) { normsTable = new NormsIndexesTableType(); if (!normsTable->reserve(polyVertCount) || !mesh->reservePerTriangleNormalIndexes()) { ccLog::Warning(QString("[FBX] Not enough memory to load mesh '%1' normals!").arg(fbxMesh->GetName())); normsTable->release(); normsTable = 0; } else { mesh->setTriNormsTable(normsTable); vertices->showNormals(true); mesh->showNormals(true); } } //materials ccMaterialSet* materials = 0; { FbxNode* lNode = fbxMesh->GetNode(); int lMaterialCount = lNode ? lNode->GetMaterialCount() : 0; for (int i=0; i<lMaterialCount; i++) { FbxSurfaceMaterial *lBaseMaterial = lNode->GetMaterial(i); bool isLambert = lBaseMaterial->GetClassId().Is(FbxSurfaceLambert::ClassId); bool isPhong = lBaseMaterial->GetClassId().Is(FbxSurfacePhong::ClassId); if (isLambert || isPhong) { ccMaterial::Shared mat(new ccMaterial(lBaseMaterial->GetName())); FbxSurfaceLambert* lLambertMat = static_cast<FbxSurfaceLambert*>(lBaseMaterial); float ambient[4]; float diffuse[4]; float emission[4]; float specular[4]; FbxSurfacePhong* lPhongMat = isPhong ? static_cast<FbxSurfacePhong*>(lBaseMaterial) : 0; for (int k=0; k<3; ++k) { ambient[k] = static_cast<float>(lLambertMat->Ambient.Get()[k]); diffuse[k] = static_cast<float>(lLambertMat->Diffuse.Get()[k]); emission[k] = static_cast<float>(lLambertMat->Emissive.Get()[k]); if (lPhongMat) { specular[k] = static_cast<float>(lPhongMat->Specular.Get()[k]); } } mat->setAmbient(ambient); mat->setDiffuse(diffuse); mat->setEmission(emission); if (isPhong) { mat->setSpecular(specular); assert(lPhongMat); mat->setShininess(static_cast<float>(lPhongMat->Shininess)); } //import associated texture (if any) { int lTextureIndex; FBXSDK_FOR_EACH_TEXTURE(lTextureIndex) { FbxProperty lProperty = lBaseMaterial->FindProperty(FbxLayerElement::sTextureChannelNames[lTextureIndex]); if( lProperty.IsValid() ) { int lTextureCount = lProperty.GetSrcObjectCount<FbxTexture>(); FbxTexture* texture = 0; //we can handle only one texture per material! We'll take the non layered one by default (if any) for (int j = 0; j < lTextureCount; ++j) { //Here we have to check if it's layeredtextures, or just textures: FbxLayeredTexture *lLayeredTexture = lProperty.GetSrcObject<FbxLayeredTexture>(j); if (lLayeredTexture) { //we don't handle layered textures! /*int lNbTextures = lLayeredTexture->GetSrcObjectCount<FbxTexture>(); for (int k=0; k<lNbTextures; ++k) { FbxTexture* lTexture = lLayeredTexture->GetSrcObject<FbxTexture>(k); if(lTexture) { } } //*/ } else { //non-layered texture FbxTexture* lTexture = lProperty.GetSrcObject<FbxTexture>(j); if(lTexture) { //we take the first non layered texture by default texture = lTexture; break; } } } if (texture) { FbxFileTexture *lFileTexture = FbxCast<FbxFileTexture>(texture); if (lFileTexture) { const char* texAbsoluteFilename = lFileTexture->GetFileName(); ccLog::PrintDebug(QString("[FBX] Texture absolue filename: %1").arg(texAbsoluteFilename)); if (texAbsoluteFilename != 0 && texAbsoluteFilename[0] != 0) { if (!mat->loadAndSetTexture(texAbsoluteFilename)) { ccLog::Warning(QString("[FBX] Failed to load texture file: %1").arg(texAbsoluteFilename)); } } } } } } } if (!materials) { materials = new ccMaterialSet("materials"); mesh->addChild(materials); } materials->addMaterial(mat); } else { ccLog::Warning(QString("[FBX] Material '%1' has an unhandled type").arg(lBaseMaterial->GetName())); } }
//------------------------------------------------------------------------- // //------------------------------------------------------------------------- bool UnFbx::FFbxImporter::CreateAndLinkExpressionForMaterialProperty( FbxSurfaceMaterial& FbxMaterial, UMaterial* UnrealMaterial, const char* MaterialProperty , FExpressionInput& MaterialInput, bool bSetupAsNormalMap, TArray<FString>& UVSet ) { bool bCreated = false; FbxProperty FbxProperty = FbxMaterial.FindProperty( MaterialProperty ); if( FbxProperty.IsValid() ) { int32 LayeredTextureCount = FbxProperty.GetSrcObjectCount(FbxLayeredTexture::ClassId); if (LayeredTextureCount>0) { UE_LOG(LogFbxMaterialImport, Warning,TEXT("Layered TEXTures are not supported (material %s)"),ANSI_TO_TCHAR(FbxMaterial.GetName())); } else { int32 TextureCount = FbxProperty.GetSrcObjectCount(FbxTexture::ClassId); if (TextureCount>0) { for(int32 TextureIndex =0; TextureIndex<TextureCount; ++TextureIndex) { FbxFileTexture* FbxTexture = FbxProperty.GetSrcObject(FBX_TYPE(FbxFileTexture), TextureIndex); // create an unreal texture asset UTexture* UnrealTexture = ImportTexture(FbxTexture, bSetupAsNormalMap); if (UnrealTexture) { // and link it to the material UMaterialExpressionTextureSample* UnrealTextureExpression = ConstructObject<UMaterialExpressionTextureSample>( UMaterialExpressionTextureSample::StaticClass(), UnrealMaterial ); UnrealMaterial->Expressions.Add( UnrealTextureExpression ); MaterialInput.Expression = UnrealTextureExpression; UnrealTextureExpression->Texture = UnrealTexture; UnrealTextureExpression->SamplerType = bSetupAsNormalMap ? SAMPLERTYPE_Normal : SAMPLERTYPE_Color; // add/find UVSet and set it to the texture FbxString UVSetName = FbxTexture->UVSet.Get(); FString LocalUVSetName = ANSI_TO_TCHAR(UVSetName.Buffer()); int32 SetIndex = UVSet.Find(LocalUVSetName); UMaterialExpressionTextureCoordinate* MyCoordExpression = ConstructObject<UMaterialExpressionTextureCoordinate>( UMaterialExpressionTextureCoordinate::StaticClass(), UnrealMaterial ); UnrealMaterial->Expressions.Add( MyCoordExpression ); MyCoordExpression->CoordinateIndex = (SetIndex >= 0)? SetIndex: 0; UnrealTextureExpression->Coordinates.Expression = MyCoordExpression; if ( !bSetupAsNormalMap ) { UnrealMaterial->BaseColor.Expression = UnrealTextureExpression; } else { UnrealMaterial->Normal.Expression = UnrealTextureExpression; } bCreated = true; } } } if (MaterialInput.Expression) { TArray<FExpressionOutput> Outputs = MaterialInput.Expression->GetOutputs(); FExpressionOutput* Output = Outputs.GetTypedData(); MaterialInput.Mask = Output->Mask; MaterialInput.MaskR = Output->MaskR; MaterialInput.MaskG = Output->MaskG; MaterialInput.MaskB = Output->MaskB; MaterialInput.MaskA = Output->MaskA; } } } return bCreated; }
void UnFbx::FFbxImporter::ImportTexturesFromNode(FbxNode* Node) { FbxProperty Property; int32 NbMat = Node->GetMaterialCount(); // visit all materials int32 MaterialIndex; for (MaterialIndex = 0; MaterialIndex < NbMat; MaterialIndex++) { FbxSurfaceMaterial *Material = Node->GetMaterial(MaterialIndex); //go through all the possible textures if(Material) { int32 TextureIndex; FBXSDK_FOR_EACH_TEXTURE(TextureIndex) { Property = Material->FindProperty(FbxLayerElement::sTextureChannelNames[TextureIndex]); if( Property.IsValid() ) { FbxTexture * lTexture= NULL; //Here we have to check if it's layered textures, or just textures: int32 LayeredTextureCount = Property.GetSrcObjectCount(FbxLayeredTexture::ClassId); FbxString PropertyName = Property.GetName(); if(LayeredTextureCount > 0) { for(int32 LayerIndex=0; LayerIndex<LayeredTextureCount; ++LayerIndex) { FbxLayeredTexture *lLayeredTexture = FbxCast <FbxLayeredTexture>(Property.GetSrcObject(FbxLayeredTexture::ClassId, LayerIndex)); int32 NbTextures = lLayeredTexture->GetSrcObjectCount(FbxTexture::ClassId); for(int32 TexIndex =0; TexIndex<NbTextures; ++TexIndex) { FbxFileTexture* Texture = FbxCast <FbxFileTexture> (lLayeredTexture->GetSrcObject(FbxFileTexture::ClassId,TexIndex)); if(Texture) { ImportTexture(Texture, PropertyName == FbxSurfaceMaterial::sNormalMap || PropertyName == FbxSurfaceMaterial::sBump); } } } } else { //no layered texture simply get on the property int32 NbTextures = Property.GetSrcObjectCount(FbxTexture::ClassId); for(int32 TexIndex =0; TexIndex<NbTextures; ++TexIndex) { FbxFileTexture* Texture = FbxCast <FbxFileTexture> (Property.GetSrcObject(FbxFileTexture::ClassId,TexIndex)); if(Texture) { ImportTexture(Texture, PropertyName == FbxSurfaceMaterial::sNormalMap || PropertyName == FbxSurfaceMaterial::sBump); } } } } } }//end if(Material) }// end for MaterialIndex }
//-------------------------------------------------------------------------------------- void FBXScene::ProcessMaterials(FbxScene* pScene) { for( int i = 0; i < pScene->GetMaterialCount(); ++i ) { Material* pMaterial = new Material(i); FbxSurfaceMaterial* pFBXMaterial = pScene->GetMaterial(i); FbxProperty diffuseTextureProperty = pFBXMaterial->FindProperty(FbxSurfaceMaterial::sDiffuse); if( diffuseTextureProperty.IsValid() ) { FbxFileTexture* pDiffuseTexture = diffuseTextureProperty.GetSrcObject<FbxFileTexture>(0); if( pDiffuseTexture ) { std::string strFileName = pDiffuseTexture->GetFileName(); if( strFileName.length() == 0 ) strFileName = pDiffuseTexture->GetRelativeFileName(); strFileName = GetFileFromPath(strFileName); pMaterial->SetDiffuseTextureName(strFileName); } } FbxProperty normalTextureProperty = pFBXMaterial->FindProperty(FbxSurfaceMaterial::sNormalMap); if( normalTextureProperty.IsValid() ) { FbxFileTexture* pNormalTexture = normalTextureProperty.GetSrcObject<FbxFileTexture>(0); if( pNormalTexture ) { std::string strFileName = pNormalTexture->GetFileName(); if( strFileName.length() == 0 ) strFileName = pNormalTexture->GetRelativeFileName(); strFileName = GetFileFromPath(strFileName); pMaterial->SetNormalTextureName(strFileName); } } FbxSurfaceLambert* pLambert = FbxCast<FbxSurfaceLambert>(pFBXMaterial); FbxSurfacePhong* pPhong = FbxCast<FbxSurfacePhong>(pFBXMaterial); BTHFBX_VEC3 AmbientColor2; BTHFBX_VEC3 EmissiveColor2; BTHFBX_VEC3 DiffuseColor2; BTHFBX_VEC3 SpecularColor2; float fSpecularPower = 1.0f; float fTransparency = 1.0f; if( pLambert ) { AmbientColor2 = GetMaterialColor2(pLambert->Ambient, pLambert->AmbientFactor); EmissiveColor2 = GetMaterialColor2(pLambert->Emissive, pLambert->EmissiveFactor); DiffuseColor2 = GetMaterialColor2(pLambert->Diffuse, pLambert->DiffuseFactor); FbxPropertyT<FbxDouble> FBXTransparencyProperty = pLambert->TransparencyFactor; if( FBXTransparencyProperty.IsValid() ) fTransparency = (float)FBXTransparencyProperty.Get(); } if( pPhong ) { SpecularColor2 = GetMaterialColor2(pPhong->Specular, pPhong->SpecularFactor); FbxPropertyT<FbxDouble> FBXSpecularPowerProperty = pPhong->Shininess; if( FBXSpecularPowerProperty.IsValid() ) fSpecularPower = (float)FBXSpecularPowerProperty.Get(); } pMaterial->SetAmbientColor2(AmbientColor2); pMaterial->SetEmissiveColor2(EmissiveColor2); pMaterial->SetDiffuseColor2(DiffuseColor2); pMaterial->SetSpecularColor2(SpecularColor2); pMaterial->SetSpecularPower(fSpecularPower); pMaterial->SetTransparency(fTransparency); pMaterial->AddTexturePath( GetFilePath(this->mFilename) + "/" ); m_Materials.push_back(pMaterial); m_FBXMaterials.push_back(pFBXMaterial); } }
//------------------------------------------------------------------------------------------------------------------------------------------- void transferMaterials(FbxGeometry* fbxMesh, Mesh* mesh){ int numMaterials = 0; if (fbxMesh == NULL){ throw new Exception("fbxMesh can not be NULL !"); } FbxNode* fbxNode = NULL; fbxNode = fbxMesh->GetNode(); if (fbxNode){ numMaterials = fbxNode->GetMaterialCount(); } LOG_DEBUG << " Number of materials: " << numMaterials; if (numMaterials > 0) { FbxPropertyT<FbxDouble3> lKFbxDouble3; FbxPropertyT<FbxDouble> lKFbxDouble1; FbxColor theColor; for (int matId = 0; matId < numMaterials; matId++){ Material* material = new Material(); FbxSurfaceMaterial* fbxMaterial = fbxNode->GetMaterial(matId); // Get the implementation to see f it's a hardware shader const FbxImplementation* fbxImplementation = GetImplementation(fbxMaterial, FBXSDK_IMPLEMENTATION_HLSL); string fbxImplementationType = "HLSL"; if (fbxImplementation != NULL){ fbxImplementation = GetImplementation(fbxMaterial, FBXSDK_IMPLEMENTATION_CGFX); fbxImplementationType = "CFGX"; } if (fbxImplementation) { // Handle hardware shader // TODO: transfer material using hardware shader } else if (fbxMaterial->GetClassId().Is(FbxSurfacePhong::ClassId)) { // Handle phong shader // Transfer Ambient color lKFbxDouble3 = ((FbxSurfacePhong*)fbxMaterial)->Ambient; material->Ambient = Vector4s(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2], 1); // Transfer Diffuse color lKFbxDouble3 = ((FbxSurfacePhong*)fbxMaterial)->Diffuse; material->Diffuse = Vector4s(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2], 1); // Transfer Specular color lKFbxDouble3 = ((FbxSurfacePhong*)fbxMaterial)->Specular; material->Specular = Vector4s(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2], 1); // Transfer Emissive color lKFbxDouble3 = ((FbxSurfacePhong*)fbxMaterial)->Emissive; material->Emissive = Vector4s(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2], 1); // Transfer Transperency factor lKFbxDouble1 = ((FbxSurfacePhong*)fbxMaterial)->TransparencyFactor; material->Opacity = 1.0 - lKFbxDouble1.Get(); // Transfer Shininess lKFbxDouble3 = ((FbxSurfacePhong*)fbxMaterial)->Shininess; material->Shininess = lKFbxDouble1.Get(); // Transfer Reflectivity lKFbxDouble3 = ((FbxSurfacePhong*)fbxMaterial)->ReflectionFactor; material->Reflectivity = lKFbxDouble1.Get(); } else if (fbxMaterial->GetClassId().Is(FbxSurfaceLambert::ClassId)) { // Handle Lambert shader lKFbxDouble3 = ((FbxSurfaceLambert *)fbxMaterial)->Ambient; material->Ambient = Vector4s(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2], 1); // Display the Diffuse Color lKFbxDouble3 = ((FbxSurfaceLambert *)fbxMaterial)->Diffuse; material->Diffuse = Vector4s(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2], 1); // Display the Emissive lKFbxDouble3 = ((FbxSurfaceLambert *)fbxMaterial)->Emissive; material->Emissive = Vector4s(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2], 1); // Display the Opacity lKFbxDouble1 = ((FbxSurfaceLambert *)fbxMaterial)->TransparencyFactor; material->Opacity = 1.0 - lKFbxDouble1.Get(); } else { LOG_WARNING << "Unknown type of Material !"; } FbxPropertyT<FbxString> fbxString; fbxString = fbxMaterial->ShadingModel; material->ShadingMode = fbxString.Get(); mesh->Materials.push_back(material); } } LOG_DEBUG << "Transfer materials successfully! "; }
void MeshImporter::LoadMaterials(FbxNode* node, MeshEntry* mesh, ID3D11Device3* device, ID3D11DeviceContext3* context) { int mcount = node->GetSrcObjectCount<FbxSurfaceMaterial>(); for (int index = 0; index < mcount; index++) { FbxSurfaceMaterial *material = (FbxSurfaceMaterial*)node->GetSrcObject<FbxSurfaceMaterial>(index); if (material) { // This only gets the material of type sDiffuse, you // probably need to traverse all Standard Material Property // by its name to get all possible textures. FbxProperty prop = material->FindProperty(FbxSurfaceMaterial::sDiffuse); // Check if it's layeredtextures int layered_texture_count = prop.GetSrcObjectCount<FbxLayeredTexture>(); if (layered_texture_count > 0) { for (int j = 0; j < layered_texture_count; j++) { FbxLayeredTexture* layered_texture = FbxCast<FbxLayeredTexture>(prop.GetSrcObject<FbxLayeredTexture>(j)); int lcount = layered_texture->GetSrcObjectCount<FbxTexture>(); for (int k = 0; k < lcount; k++) { FbxTexture* texture = FbxCast<FbxTexture>(layered_texture->GetSrcObject<FbxTexture>(k)); // Then, you can get all the properties of the texture, include its name const char* texture_name = texture->GetName(); // Load files LoadTexture(texture_name, mesh, device, context); PrintTab(to_string(layered_texture_count) + " Layered textures loaded!" + "Number of layers: " + to_string(lcount)); } } } else { // Directly get textures int texture_count = prop.GetSrcObjectCount<FbxTexture>(); for (int j = 0; j < texture_count; j++) { const FbxTexture* texture = FbxCast<FbxTexture>(prop.GetSrcObject<FbxTexture>(j)); // Then, you can get all the properties of the texture, include its name const char* texture_name = texture->GetName(); // Load file LoadTexture(texture_name, mesh, device, context); PrintTab(to_string(texture_count) + " Single texture loaded!"); } } } } }
//THIS MUST HAPPEN AFTER IMPORTING SKELETONS. //----------------------------------------------------------------------------------- static void ImportMesh(SceneImport* import, FbxMesh* mesh, MatrixStack4x4& matrixStack, std::map<int, FbxNode*>& nodeToJointIndex) { MeshBuilder builder = MeshBuilder(); ASSERT_OR_DIE(mesh->IsTriangleMesh(), "Was unable to load the mesh, it's not a triangle mesh!"); Matrix4x4 geoTransform = GetGeometricTransform(mesh); matrixStack.Push(geoTransform); int controlPointCount = mesh->GetControlPointsCount(); //Figure out our weighs for all verts before importing any of them std::vector<SkinWeight> skinWeights; if (HasSkinWeights(mesh)) { skinWeights.resize(controlPointCount); GetSkinWeights(import, skinWeights, mesh, nodeToJointIndex); } else { FbxNode* node = mesh->GetNode(); //Walk tree up till you reach the node associated with that joint. //Find the first parent node that has a joint associated with it //All vertices (fully weighted) //All Skin Weights = indices{jointINdex, 0, 0, 0 } weights{1.0f, 0.0f, 0.0f, 0.0f}; int jointIndex = Skeleton::INVALID_JOINT_INDEX; for (auto iter = nodeToJointIndex.begin(); iter != nodeToJointIndex.end(); ++iter) { if (iter->second == node) { jointIndex = iter->first; break; } } if (jointIndex == Skeleton::INVALID_JOINT_INDEX) { for (unsigned int i = 0; i < skinWeights.size(); ++i) { skinWeights[i].indices = Vector4Int::ZERO; skinWeights[i].weights = Vector4::UNIT_X; } } else { for (unsigned int i = 0; i < skinWeights.size(); ++i) { skinWeights[i].indices = Vector4Int(jointIndex, 0, 0, 0); skinWeights[i].weights = Vector4::UNIT_X; } } } builder.Begin(); { Matrix4x4 transform = matrixStack.GetTop(); int polyCount = mesh->GetPolygonCount(); for (int polyIndex = 0; polyIndex < polyCount; ++polyIndex) { int vertCount = mesh->GetPolygonSize(polyIndex); ASSERT_OR_DIE(vertCount == 3, "Vertex count was not 3"); for (int vertIndex = 0; vertIndex < vertCount; ++vertIndex) { ImportVertex(builder, transform, mesh, polyIndex, vertIndex, skinWeights); } } } builder.End(); FbxSurfaceMaterial* material = mesh->GetNode()->GetMaterial(0); builder.SetMaterialName(material->GetName()); matrixStack.Pop(); import->meshes.push_back(builder); }
void Tools::DisplayMaterial::DisplayMaterial( FbxGeometry *i_geometry ) { DisplayCommon::DisplayString( "\n\n--------------------\nMaterial\n--------------------" ); int materialCount = 0; FbxNode *node = NULL; if( i_geometry ) { node = i_geometry->GetNode(); if( node ) materialCount = node->GetMaterialCount(); } if( materialCount > 0 ) { FbxPropertyT<FbxDouble3> double3; FbxPropertyT<FbxDouble> double1; FbxColor theColor; for( int ctr = 0; ctr < materialCount; ctr++ ) { DisplayCommon::DisplayInt( " Material ", ctr ); FbxSurfaceMaterial *material = node->GetMaterial( ctr ); DisplayCommon::DisplayString( " Name: \"", (char *) material->GetName(), "\"" ); #ifdef DISPLAY_HARDWARE_SHADER_INFORMATION //Get the implementation to see if it's a hardware shader. // Note:: this cause memory leak const FbxImplementation* implementation = GetImplementation( material, FBXSDK_IMPLEMENTATION_HLSL ); FbxString implementationType = "HLSL"; if( !implementation ) { implementation = GetImplementation( material, FBXSDK_IMPLEMENTATION_CGFX ); implementationType = "CGFX"; } if( implementation ) { //Now we have a hardware shader, let's read it FBXSDK_printf( " Hardware Shader Type: %s\n", implemenationType.Buffer() ); DisplayCommon::DisplayString( " Hardware Shader Type: ", implemenationType ); const FbxBindingTable* rootTable = implementation->GetRootTable(); FbxString fileName = rootTable->DescAbsoluteURL.Get(); FbxString techniqueName = rootTable->DescTAG.Get(); const FbxBindingTable* table = implementation->GetRootTable(); size_t entryNum = table->GetEntryCount(); for( int i = 0; i < (int)entryNum; i++ ) { const FbxBindingTableEntry& entry = table->GetEntry( i ); const char *entrySrcType = entry.GetEntryType( true ); FbxProperty fbxProp; FbxString test = entry.GetSource(); FBXSDK_printf( " Entry: %s\n", test.Buffer() ); DisplayCommon::DisplayString( " Entry: %s\n", test ); if ( strcmp( FbxPropertyEntryView::sEntryType, entrySrcType ) == 0 ) { fbxProp = material->FindPropertyHierarchical(entry.GetSource()); if( !fbxProp.IsValid() ) { fbxProp = material->RootProperty.FindHierarchical( entry.GetSource() ); } } else if( strcmp( FbxConstantEntryView::sEntryType, entrySrcType ) == 0 ) { fbxProp = implementation->GetConstants().FindHierarchical( entry.GetSource() ); } if( fbxProp.IsValid() ) { if( fbxProp.GetSrcObjectCount<FbxTexture>() > 0 ) { //do what you want with the textures for( int j = 0; j < fbxProp.GetSrcObjectCount<FbxFileTexture>(); j++ ) { FbxFileTexture *tex = fbxProp.GetSrcObject<FbxFileTexture>( j ); FBXSDK_printf( " File Texture: %s\n", tex->GetFileName() ); DisplayCommon::DisplayString( " File Texture: %s\n", tex->GetFileName() ); } for( int j = 0; j < fbxProp.GetSrcObjectCount<FbxLayeredTexture>(); j++ ) { FbxLayeredTexture *tex = fbxProp.GetSrcObject<FbxLayeredTexture>( j ); FBXSDK_printf( " Layered Texture: %s\n", tex->GetName() ); DisplayCommon::DisplayString( " Layered Texture: %s\n", tex->GetName() ); } for( int j = 0; j < fbxProp.GetSrcObjectCount<FbxProceduralTexture>(); j++ ) { FbxProceduralTexture *tex = fbxProp.GetSrcObject<FbxProceduralTexture>( j ); FBXSDK_printf( " Procedural Texture: %s\n", tex->GetName() ); DisplayCommon::DisplayString( " Procedural Texture: %s\n", tex->GetName() ); } } else { FbxDataType fbxType = fbxProp.GetPropertyDataType(); FbxString fbxName = fbxType.GetName(); if( FbxBoolDT == fbxType ) { DisplayCommon::DisplayBool( " Bool: ", fbxProp.Get<FbxBool>() ); } else if( FbxIntDT == fbxType || FbxEnumDT == fbxType ) { DisplayCommon::DisplayInt( " Int: ", fbxProp.Get<FbxInt>() ); } else if( FbxFloatDT == fbxType ) { DisplayCommon::DisplayDouble( " Float: ", fbxProp.Get<FbxFloat>() ); } else if( FbxDoubleDT == fbxType ) { DisplayCommon::DisplayDouble( " Double: ", fbxProp.Get<FbxDouble>() ); } else if( FbxStringDT == fbxType || FbxUrlDT == fbxType || FbxXRefUrlDT == fbxType ) { DisplayCommon::DisplayString( " String: ", fbxProp.Get<FbxString>().Buffer() ); } else if( FbxDouble2DT == fbxType ) { FbxDouble2 double2 = fbxProp.Get<FbxDouble2>(); FbxVector2 vector; vector[0] = double2[0]; vector[1] = double2[1]; DisplayCommon::Display2DVector( " 2D vector: ", vector ); } else if( (FbxDouble3DT == fbxType) || (FbxColor3DT == fbxType) ) { FbxDouble3 double3 = fbxProp.Get<FbxDouble3>(); FbxVector4 vector; vector[0] = double3[0]; vector[1] = double3[1]; vector[2] = double3[2]; DisplayCommon::Display3DVector( " 3D vector: ", vector ); } else if( (FbxDouble4DT == fbxType) || (FbxColor4DT == fbxType) ) { FbxDouble4 double4 = fbxProp.Get<FbxDouble4>(); FbxVector4 vector; vector[0] = double4[0]; vector[1] = double4[1]; vector[2] = double4[2]; vector[3] = double4[3]; DisplayCommon::Display4DVector( " 4D vector: ", vector ); } else if( FbxDouble4x4DT == fbxType ) { FbxDouble4x4 double44 = fbxProp.Get<FbxDouble4x4>(); for( int j = 0; j < 4; j++ ) { FbxVector4 vector; vector[0] = double44[j][0]; vector[1] = double44[j][1]; vector[2] = double44[j][2]; vector[3] = double44[j][3]; DisplayCommon::Display4DVector( " 4x4D vector: ", vector ); } } } } } } else #endif // #ifdef DISPLAY_HARDWARE_SHADER_INFORMATION if( material->GetClassId().Is(FbxSurfacePhong::ClassId) ) { // We found a Phong material. Display its properties. // Display the Ambient Color double3 = ((FbxSurfacePhong *) material)->Ambient; theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] ); DisplayCommon::DisplayColor( " Ambient: ", theColor ); // Display the Diffuse Color double3 = ((FbxSurfacePhong *) material)->Diffuse; theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] ); DisplayCommon::DisplayColor( " Diffuse: ", theColor ); // Display the Specular Color (unique to Phong materials) double3 = ((FbxSurfacePhong *) material)->Specular; theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] ); DisplayCommon::DisplayColor( " Specular: ", theColor ); // Display the Emissive Color double3 = ((FbxSurfacePhong *) material)->Emissive; theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] ); DisplayCommon::DisplayColor( " Emissive: ", theColor ); //Opacity is Transparency factor now double1 = ((FbxSurfacePhong *) material)->TransparencyFactor; DisplayCommon::DisplayDouble( " Opacity: ", 1.0-double1.Get() ); // Display the Shininess double1 = ((FbxSurfacePhong *) material)->Shininess; DisplayCommon::DisplayDouble( " Shininess: ", double1.Get() ); // Display the Reflectivity double1 = ((FbxSurfacePhong *) material)->ReflectionFactor; DisplayCommon::DisplayDouble( " Reflectivity: ", double1.Get() ); } else if( material->GetClassId().Is(FbxSurfaceLambert::ClassId) ) { // We found a Lambert material. Display its properties. // Display the Ambient Color double3 = ((FbxSurfaceLambert *)material)->Ambient; theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] ); DisplayCommon::DisplayColor( " Ambient: ", theColor ); // Display the Diffuse Color double3 = ((FbxSurfaceLambert *)material)->Diffuse; theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] ); DisplayCommon::DisplayColor( " Diffuse: ", theColor ); // Display the Emissive double3 = ((FbxSurfaceLambert *)material)->Emissive; theColor.Set( double3.Get()[0], double3.Get()[1], double3.Get()[2] ); DisplayCommon::DisplayColor( " Emissive: ", theColor ); // Display the Opacity double1 = ((FbxSurfaceLambert *)material)->TransparencyFactor; DisplayCommon::DisplayDouble( " Opacity: ", 1.0-double1.Get() ); } else DisplayCommon::DisplayString( "Unknown type of Material" ); FbxPropertyT<FbxString> string; string = material->ShadingModel; DisplayCommon::DisplayString( " Shading Model: ", string.Get() ); } } }
/** * 相対パスのファイル名をテクスチャのファイル名として再帰的に設定する * * @param node FbxNode */ void FbxFileLoader::set_relative_file_name_to_texture_file_name_recursive( FbxNode* node ) { if ( ! node ) { return; } for ( int n = 0; n < node->GetMaterialCount(); n++ ) { FbxSurfaceMaterial* material = node->GetMaterial( n ); if ( ! material ) { continue; } for ( auto p = material->GetFirstProperty(); p.IsValid(); p = material->GetNextProperty( p ) ) { for ( int m = 0; m < p.GetSrcObjectCount< FbxTexture >(); m++ ) { FbxLayeredTexture* layered_texture = p.GetSrcObject< FbxLayeredTexture >( m ); FbxFileTexture* file_texture = nullptr; if ( layered_texture ) { for ( int l = 0; l < layered_texture->GetSrcObjectCount< FbxTexture >(); l++ ) { if ( ! layered_texture->GetSrcObject< FbxTexture >( l ) ) { continue; } file_texture = FbxCast< FbxFileTexture >( layered_texture->GetSrcObject< FbxTexture >( l ) ); } } else { if ( ! p.GetSrcObject< FbxTexture >( m ) ) { continue; } file_texture = FbxCast< FbxFileTexture >( p.GetSrcObject< FbxTexture >( m ) ); } if ( file_texture ) { const string_t relative_file_name = file_texture->GetRelativeFileName(); if ( ! file_texture->SetFileName( relative_file_name.c_str() ) ) { COMMON_THROW_EXCEPTION_MESSAGE( string_t( "FbxFileTexture::SetFileName failed : " ) + relative_file_name ); } /* if ( ! file_texture->SetRelativeFileName( relative_file_name.c_str() ) ) { COMMON_THROW_EXCEPTION_MESSAGE( string_t( "FbxFileTexture::SetRelativeFileName failed : " ) + relative_file_name ); } */ } } } } for ( int n = 0; n < node->GetChildCount(); n++ ) { set_relative_file_name_to_texture_file_name_recursive( node->GetChild( n ) ); } }
bool FillData(ModelData* someData,FbxNode* aNode, AnimationData* aAnimation) { FbxMesh* mesh = aNode->GetMesh(); if (mesh == nullptr || !aNode) return false; const int lPolygonCount = mesh->GetPolygonCount(); // Count the polygon count of each material FbxLayerElementArrayTemplate<int>* lMaterialIndice = NULL; FbxGeometryElement::EMappingMode lMaterialMappingMode = FbxGeometryElement::eNone; if (mesh->GetElementMaterial()) { lMaterialIndice = &mesh->GetElementMaterial()->GetIndexArray(); lMaterialMappingMode = mesh->GetElementMaterial()->GetMappingMode(); if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon) { FBX_ASSERT(lMaterialIndice->GetCount() == lPolygonCount); if (lMaterialIndice->GetCount() == lPolygonCount) { // Count the faces of each material for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex) { const int lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex); lMaterialIndex; /*if (someData->mSubMeshes[lMaterialIndex] == NULL) { someData->mSubMeshes[lMaterialIndex] = new ModelData::SubMesh; } someData->mSubMeshes[lMaterialIndex]->TriangleCount += 1;*/ } // Make sure we have no "holes" (NULL) in the mSubMeshes table. This can happen // if, in the loop above, we resized the mSubMeshes by more than one slot. /*for (int i = 0; i < someData->mSubMeshes.Count(); i++) { if (someData->mSubMeshes[i] == NULL) someData->mSubMeshes[i] = new ModelData::SubMesh; }*/ // Record the offset (how many vertex) const int lMaterialCount = someData->mSubMeshes.Size(); lMaterialCount; int lOffset = 0; /*for (int lIndex = 0; lIndex < lMaterialCount; ++lIndex) { someData->mSubMeshes[lIndex]->IndexOffset = lOffset; lOffset += someData->mSubMeshes[lIndex]->TriangleCount * 3; // This will be used as counter in the following procedures, reset to zero someData->mSubMeshes[lIndex]->TriangleCount = 0; }*/ FBX_ASSERT(lOffset == lPolygonCount * 3); } } } // All faces will use the same material. if (someData->mSubMeshes.Size() == 0) { if (someData->mSubMeshes.GetCapacity() == 0) { someData->mSubMeshes.Init(1); } someData->mSubMeshes.RemoveAll(); someData->mSubMeshes.AddEmptyObject(); someData->mSubMeshes[0] = new ModelData::SubMesh(); } bool hasNormalMap = false; const int lMaterialCount = aNode->GetMaterialCount(); for (int lMaterialIndex = 0; lMaterialIndex < lMaterialCount; ++lMaterialIndex) { FbxSurfaceMaterial * lMaterial = aNode->GetMaterial(lMaterialIndex); if (lMaterial && !lMaterial->GetUserDataPtr()) { TextureInfo diffuseInfo; GetMaterialProperty(lMaterial,FbxSurfaceMaterial::sDiffuse,FbxSurfaceMaterial::sDiffuseFactor,diffuseInfo.myFileName); diffuseInfo.myType = DIFFUSE; if(diffuseInfo.myFileName.empty() == false) { someData->myTextures.push_back(diffuseInfo); } TextureInfo normalInfo; GetMaterialProperty(lMaterial,FbxSurfaceMaterial::sNormalMap,FbxSurfaceMaterial::sBumpFactor,normalInfo.myFileName); hasNormalMap = normalInfo.myFileName.empty() == false; normalInfo.myType = NORMALMAP; if(normalInfo.myFileName.empty() == false) { someData->myTextures.push_back(normalInfo); hasNormalMap = true; } TextureInfo roughnessInfo; GetMaterialProperty(lMaterial,FbxSurfaceMaterial::sSpecular,FbxSurfaceMaterial::sSpecularFactor,roughnessInfo.myFileName); roughnessInfo.myType = ROUGHNESS; if(roughnessInfo.myFileName.empty() == false) { someData->myTextures.push_back(roughnessInfo); } TextureInfo substanceInfo; GetMaterialProperty(lMaterial,FbxSurfaceMaterial::sReflection,FbxSurfaceMaterial::sReflectionFactor,substanceInfo.myFileName); substanceInfo.myType = SUBSTANCE; if(substanceInfo.myFileName.empty() == false) { someData->myTextures.push_back(substanceInfo); } TextureInfo ambientInfo; GetMaterialProperty(lMaterial, FbxSurfaceMaterial::sAmbient, FbxSurfaceMaterial::sAmbientFactor, ambientInfo.myFileName); ambientInfo.myType = AO; if (substanceInfo.myFileName.empty() == false) { someData->myTextures.push_back(ambientInfo); } } } // Congregate all the data of a mesh to be cached in VBOs. // If normal or UV is by polygon vertex, record all vertex attributes by polygon vertex.' someData->mHasNormal = mesh->GetElementNormalCount() > 0; someData->mHasUV = mesh->GetElementUVCount() > 0; someData->myHasBiNormal = mesh->GetElementBinormalCount() > 0; FbxSkin * lSkinDeformer = (FbxSkin *)mesh->GetDeformer(0, FbxDeformer::eSkin); someData->myHasSkinweights = lSkinDeformer != nullptr; if(hasNormalMap && someData->myHasBiNormal == false) { mesh->GenerateTangentsDataForAllUVSets(); someData->myHasBiNormal = mesh->GetElementBinormalCount() > 0; } someData->myHasTangents = mesh->GetElementTangentCount() > 0; FbxGeometryElement::EMappingMode lNormalMappingMode = FbxGeometryElement::eNone; FbxGeometryElement::EMappingMode lUVMappingMode = FbxGeometryElement::eNone; if (someData->mHasNormal) { lNormalMappingMode = mesh->GetElementNormal(0)->GetMappingMode(); if (lNormalMappingMode == FbxGeometryElement::eNone) { someData->mHasNormal = false; } if (someData->mHasNormal && lNormalMappingMode != FbxGeometryElement::eByControlPoint) { someData->mAllByControlPoint = false; } } if (someData->mHasUV) { lUVMappingMode = mesh->GetElementUV(0)->GetMappingMode(); if (lUVMappingMode == FbxGeometryElement::eNone) { someData->mHasUV = false; } if (someData->mHasUV && lUVMappingMode != FbxGeometryElement::eByControlPoint) { someData->mAllByControlPoint = false; } } // Allocate the array memory, by control point or by polygon vertex. int lPolygonVertexCount = mesh->GetControlPointsCount(); //if (!someData->my) { ModelData::Layout newLayout; newLayout.myType = ModelData::VERTEX_POS; newLayout.mySize = VERTEX_STRIDE; newLayout.myOffset = 0; someData->myLayout.Add(newLayout); lPolygonVertexCount = lPolygonCount * TRIANGLE_VERTEX_COUNT; } int stride = VERTEX_STRIDE; size_t size = lPolygonVertexCount * VERTEX_STRIDE; //float * lVertices = new float[lPolygonVertexCount * VERTEX_STRIDE]; unsigned int * lIndices = new unsigned int[lPolygonCount * TRIANGLE_VERTEX_COUNT]; someData->myIndexCount = lPolygonCount * TRIANGLE_VERTEX_COUNT; //float * lNormals = NULL; if (someData->mHasNormal) { ModelData::Layout newLayout; newLayout.myType = ModelData::VERTEX_NORMAL; newLayout.mySize = NORMAL_STRIDE; newLayout.myOffset = stride*4; someData->myLayout.Add(newLayout); stride += NORMAL_STRIDE; size += lPolygonVertexCount * NORMAL_STRIDE; //lNormals = new float[lPolygonVertexCount * NORMAL_STRIDE]; } //float * lUVs = NULL; FbxStringList lUVNames; mesh->GetUVSetNames(lUVNames); const char * lUVName = NULL; if (someData->mHasUV && lUVNames.GetCount()) { ModelData::Layout newLayout; newLayout.myType = ModelData::VERTEX_UV; newLayout.mySize = UV_STRIDE; newLayout.myOffset = stride*4; someData->myLayout.Add(newLayout); stride += UV_STRIDE; size += lPolygonVertexCount * UV_STRIDE; //lUVs = new float[lPolygonVertexCount * UV_STRIDE]; lUVName = lUVNames[0]; } if (someData->myHasBiNormal) { ModelData::Layout newLayout; newLayout.myType = ModelData::VERTEX_BINORMAL; newLayout.mySize = BINORMAL_STRIDE; newLayout.myOffset = stride*4; someData->myLayout.Add(newLayout); stride += BINORMAL_STRIDE; size += lPolygonVertexCount * BINORMAL_STRIDE; //lUVs = new float[lPolygonVertexCount * UV_STRIDE]; } if (someData->myHasTangents) { ModelData::Layout newLayout; newLayout.myType = ModelData::VERTEX_TANGENT; newLayout.mySize = TANGENT_STRIDE; newLayout.myOffset = stride*4; someData->myLayout.Add(newLayout); stride += TANGENT_STRIDE; size += lPolygonVertexCount * TANGENT_STRIDE; //lUVs = new float[lPolygonVertexCount * UV_STRIDE]; } if (someData->myHasSkinweights) { ModelData::Layout newLayout; newLayout.myType = ModelData::VERTEX_SKINWEIGHTS; newLayout.mySize = SKINWEIGHT_STRIDE; newLayout.myOffset = stride*4; someData->myLayout.Add(newLayout); stride += SKINWEIGHT_STRIDE; size += lPolygonVertexCount * SKINWEIGHT_STRIDE; newLayout.myType = ModelData::VERTEX_BONEID; newLayout.mySize = BONEID_STRIDE; newLayout.myOffset = stride*4; someData->myLayout.Add(newLayout); stride += BONEID_STRIDE; size += lPolygonVertexCount * BONEID_STRIDE; //lUVs = new float[lPolygonVertexCount * UV_STRIDE]; } float * lVertices = new float[size]; FbxAMatrix globalPos; FbxVector4* weights = nullptr; FbxVectorTemplate4<int>* bones = nullptr; FbxTime time = static_cast<FbxTime>(0.0f); if(someData->myHasSkinweights) { weights = new FbxVector4[mesh->GetControlPointsCount()]; bones = new FbxVectorTemplate4<int>[mesh->GetControlPointsCount()]; ComputeLinearDeformation(globalPos,mesh,weights,bones,aAnimation); } const FbxGeometryElementBinormal * lBiNormalElement = NULL; const FbxGeometryElementTangent * lTangentElement = NULL; if (someData->myHasBiNormal) { lBiNormalElement = mesh->GetElementBinormal(0); } if (someData->myHasTangents) { lTangentElement = mesh->GetElementTangent(0); } // Populate the array with vertex attribute, if by control point. const FbxVector4 * lControlPoints = mesh->GetControlPoints(); FbxVector4 lCurrentVertex; FbxVector4 lCurrentNormal; FbxVector4 lCurrentBiNormal; FbxVector4 lCurrentTangent; FbxVector2 lCurrentUV; if (someData->mAllByControlPoint) { const FbxGeometryElementNormal * lNormalElement = NULL; const FbxGeometryElementUV * lUVElement = NULL; if (someData->mHasNormal) { lNormalElement = mesh->GetElementNormal(0); } if (someData->mHasUV) { lUVElement = mesh->GetElementUV(0); } for (int lIndex = 0; lIndex < lPolygonVertexCount; ++lIndex) { int currentIndex = lIndex * stride; int addedSize = VERTEX_STRIDE; // Save the vertex position. lCurrentVertex = lControlPoints[lIndex]; CU::Vector4f position(static_cast<float>(lCurrentVertex[0]), static_cast<float>(lCurrentVertex[1]), static_cast<float>(lCurrentVertex[2]), 1); CU::Matrix44f fixMatrix; fixMatrix = CU::Matrix44<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1,0,0)); position = position*fixMatrix; lVertices[currentIndex] = position.x; lVertices[currentIndex + 1] = position.y; lVertices[currentIndex + 2] = position.z; lVertices[currentIndex + 3] = 1; // Save the normal. if (someData->mHasNormal) { int lNormalIndex = lIndex; if (lNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { lNormalIndex = lNormalElement->GetIndexArray().GetAt(lIndex); } lCurrentNormal = lNormalElement->GetDirectArray().GetAt(lNormalIndex); CU::Vector3f normal( static_cast<float>(lCurrentNormal[0]), static_cast<float>(lCurrentNormal[1]), static_cast<float>(lCurrentNormal[2])); normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0)); lVertices[currentIndex + addedSize] = normal.x; lVertices[currentIndex + addedSize + 1] = normal.y; lVertices[currentIndex + addedSize + 2] = normal.z; lVertices[currentIndex + addedSize + 3] = 0; addedSize += NORMAL_STRIDE; } // Save the UV. if (someData->mHasUV) { int lUVIndex = lIndex; if (lUVElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { lUVIndex = lUVElement->GetIndexArray().GetAt(lIndex); } lCurrentUV = lUVElement->GetDirectArray().GetAt(lUVIndex); lVertices[currentIndex + addedSize] = static_cast<float>(lCurrentUV[0]); lVertices[currentIndex + addedSize + 1] = static_cast<float>(lCurrentUV[1])*-1.0f; addedSize += 2; } if (someData->myHasBiNormal) { int lBinormIndexIndex = lIndex; if (lBiNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { lBinormIndexIndex = lBiNormalElement->GetIndexArray().GetAt(lIndex); } lCurrentBiNormal = lBiNormalElement->GetDirectArray().GetAt(lBinormIndexIndex); //mesh->GetElementBinormal(lPolygonIndex, lVerticeIndex, lCurrentNormal); //lCurrentNormal = lCurrentNormal CU::Vector3f normal( static_cast<float>(lCurrentBiNormal[0]), static_cast<float>(lCurrentBiNormal[1]), static_cast<float>(lCurrentBiNormal[2])); normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0)); if (CU::Length(normal) != 0.f) CU::Normalize(normal); lVertices[currentIndex + addedSize] = normal.x; lVertices[currentIndex + addedSize + 1] = normal.y; lVertices[currentIndex + addedSize + 2] = normal.z; lVertices[currentIndex + addedSize + 3] = 0; addedSize += BINORMAL_STRIDE; } if (someData->myHasTangents) { int lBinormIndexIndex = lIndex; if (lTangentElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { lBinormIndexIndex = lTangentElement->GetIndexArray().GetAt(lIndex); } lCurrentTangent = lTangentElement->GetDirectArray().GetAt(lBinormIndexIndex); //lCurrentNormal = lCurrentNormal CU::Vector3f normal( static_cast<float>(lCurrentTangent[0]), static_cast<float>(lCurrentTangent[1]), static_cast<float>(lCurrentTangent[2])); normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0)); if (CU::Length(normal) != 0.f) CU::Normalize(normal); lVertices[currentIndex + addedSize] = normal.x; lVertices[currentIndex + addedSize + 1] = normal.y; lVertices[currentIndex + addedSize + 2] = normal.z; lVertices[currentIndex + addedSize + 3] = 0; addedSize += TANGENT_STRIDE; } if(someData->myHasSkinweights) { FbxVector4 currentWeights = weights[lIndex]; //currentWeights.Normalize(); lVertices[currentIndex + addedSize] = static_cast<float>(currentWeights[0]); lVertices[currentIndex + addedSize + 1] = static_cast<float>(currentWeights[1]); lVertices[currentIndex + addedSize + 2] = static_cast<float>(currentWeights[2]); lVertices[currentIndex + addedSize + 3] = static_cast<float>(currentWeights[3]); addedSize += SKINWEIGHT_STRIDE; FbxVectorTemplate4<int> currentBones = bones[lIndex]; lVertices[currentIndex + addedSize] = static_cast<float>(currentBones[0]); lVertices[currentIndex + addedSize + 1] = static_cast<float>(currentBones[1]); lVertices[currentIndex + addedSize + 2] = static_cast<float>(currentBones[2]); lVertices[currentIndex + addedSize + 3] = static_cast<float>(currentBones[3]); addedSize += BONEID_STRIDE; } } } int lVertexCount = 0; for (int lPolygonIndex = 0; lPolygonIndex < lPolygonCount; ++lPolygonIndex) { // The material for current face. int lMaterialIndex = 0; if (lMaterialIndice && lMaterialMappingMode == FbxGeometryElement::eByPolygon) { lMaterialIndex = lMaterialIndice->GetAt(lPolygonIndex); } // Where should I save the vertex attribute index, according to the material const int lIndexOffset = someData->mSubMeshes[lMaterialIndex]->IndexOffset + someData->mSubMeshes[lMaterialIndex]->TriangleCount * 3; for (int lVerticeIndex = TRIANGLE_VERTEX_COUNT-1; lVerticeIndex > -1; --lVerticeIndex) { const int lControlPointIndex = mesh->GetPolygonVertex(lPolygonIndex, lVerticeIndex); int vertexIndex = lIndexOffset + (TRIANGLE_VERTEX_COUNT-1) - lVerticeIndex; if (someData->mAllByControlPoint) { lIndices[vertexIndex] = static_cast<unsigned int>(lControlPointIndex); } // Populate the array with vertex attribute, if by polygon vertex. else { lIndices[vertexIndex] = static_cast<unsigned int>(lVertexCount); lCurrentVertex = lControlPoints[lControlPointIndex]; int addedSize = VERTEX_STRIDE; int currentIndex = lVertexCount * stride; CU::Vector4f position(static_cast<float>(lCurrentVertex[0]), static_cast<float>(lCurrentVertex[1]), static_cast<float>(lCurrentVertex[2]), 1); //fixMatrix CU::Matrix44f fixMatrix; fixMatrix = CU::Matrix44<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0)); position = position*fixMatrix; lVertices[currentIndex] = position.x; lVertices[currentIndex + 1] = position.y; lVertices[currentIndex + 2] = position.z; lVertices[currentIndex + 3] = 0; if (someData->mHasNormal) { mesh->GetPolygonVertexNormal(lPolygonIndex, lVerticeIndex, lCurrentNormal); CU::Vector3f normal( static_cast<float>(lCurrentNormal[0]), static_cast<float>(lCurrentNormal[1]), static_cast<float>(lCurrentNormal[2])); normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0)); if (CU::Length(normal) != 0.f) CU::Normalize(normal); lVertices[currentIndex + addedSize] = normal.x; lVertices[currentIndex + addedSize + 1] = normal.y; lVertices[currentIndex + addedSize + 2] = normal.z; lVertices[currentIndex + addedSize + 3] = 0; addedSize += NORMAL_STRIDE; } if (someData->mHasUV) { bool lUnmappedUV; mesh->GetPolygonVertexUV(lPolygonIndex, lVerticeIndex, lUVName, lCurrentUV, lUnmappedUV); lVertices[currentIndex + addedSize] = static_cast<float>(lCurrentUV[0]); lVertices[currentIndex + addedSize + 1] = static_cast<float>(lCurrentUV[1])*-1.0f; addedSize += UV_STRIDE; } if (someData->myHasBiNormal) { int lBinormIndexIndex = lVerticeIndex; if (lBiNormalElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { lBinormIndexIndex = lBiNormalElement->GetIndexArray().GetAt(lVerticeIndex); } lCurrentBiNormal = lBiNormalElement->GetDirectArray().GetAt(lBinormIndexIndex); CU::Vector3f normal( static_cast<float>(lCurrentBiNormal[0]), static_cast<float>(lCurrentBiNormal[1]), static_cast<float>(lCurrentBiNormal[2])); normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0)); if (CU::Length(normal) != 0.f) CU::Normalize(normal); lVertices[currentIndex + addedSize] = normal.x; lVertices[currentIndex + addedSize + 1] = normal.y; lVertices[currentIndex + addedSize + 2] = normal.z; lVertices[currentIndex + addedSize + 3] = 0; addedSize += BINORMAL_STRIDE; } if (someData->myHasTangents) { int lBinormIndexIndex = lVerticeIndex; if (lTangentElement->GetReferenceMode() == FbxLayerElement::eIndexToDirect) { lBinormIndexIndex = lTangentElement->GetIndexArray().GetAt(lVerticeIndex); } lCurrentTangent = lTangentElement->GetDirectArray().GetAt(lBinormIndexIndex); mesh->GetPolygonVertexNormal(lPolygonIndex, lVerticeIndex, lCurrentNormal); CU::Vector3f normal( static_cast<float>(lCurrentTangent[0]), static_cast<float>(lCurrentTangent[1]), static_cast<float>(lCurrentTangent[2])); normal = normal*CU::Matrix33<float>::CreateReflectionMatrixAboutAxis(CU::Vector3f(1, 0, 0)); if (CU::Length(normal) != 0.f) CU::Normalize(normal); lVertices[currentIndex + addedSize] = normal.x; lVertices[currentIndex + addedSize + 1] = normal.y; lVertices[currentIndex + addedSize + 2] = normal.z; lVertices[currentIndex + addedSize + 3] = 0; addedSize += TANGENT_STRIDE; } if(someData->myHasSkinweights) { FbxVector4 currentWeights = weights[lControlPointIndex]; FbxVectorTemplate4<int> currentBones = bones[lControlPointIndex]; for(int l = 0;l < 4;++l) { if(currentBones[l] == -1) { currentWeights[l] = 0.0f; } } currentWeights.Normalize(); lVertices[currentIndex + addedSize] = static_cast<float>(currentWeights[0]); lVertices[currentIndex + addedSize + 1] = static_cast<float>(currentWeights[1]); lVertices[currentIndex + addedSize + 2] = static_cast<float>(currentWeights[2]); lVertices[currentIndex + addedSize + 3] = static_cast<float>(currentWeights[3]); addedSize += SKINWEIGHT_STRIDE; lVertices[currentIndex + addedSize] = *(float*)¤tBones[0]; lVertices[currentIndex + addedSize + 1] = *(float*)¤tBones[1]; lVertices[currentIndex + addedSize + 2] = *(float*)¤tBones[2]; lVertices[currentIndex + addedSize + 3] = *(float*)¤tBones[3]; addedSize += BONEID_STRIDE; } } ++lVertexCount; } someData->mSubMeshes[lMaterialIndex]->TriangleCount += 1; } someData->myVertexCount = lVertexCount; someData->myVertexStride = stride; someData->myVertexBuffer = lVertices; someData->myIndicies = lIndices; if(weights) { delete [] weights; delete [] bones; } return true; }
SceneNode *SceneConverter::makeSceneNode(FbxNode *node) { SceneNode *sceneNode = new SceneNode(); if (node->GetParent() == NULL) // The root { // Type sceneNode->type = FbxString("root"); // Name sceneNode->attributes.push_back(std::make_pair(FbxString("name"), node->GetName())); // Transformation FbxAMatrix m = node->EvaluateGlobalTransform(); const FbxVector4 translation = m.GetT(); const FbxVector4 rotation = m.GetR(); const FbxVector4 scaling = m.GetS(); char buffer[1024]; FBXSDK_sprintf(buffer, 1024, "s:%8.5f,%8.5f,%8.5f,r:%8.5f,%8.5f,%8.5f,t:%8.5f,%8.5f,%8.5f", (float)scaling[0], (float)scaling[1], (float)scaling[2], (float)rotation[0], (float)rotation[1], (float)rotation[2], (float)translation[0], (float)translation[1], (float)translation[2]); sceneNode->attributes.push_back(std::make_pair(FbxString("transform"), FbxString(buffer))); } else { FbxCamera *camera = node->GetCamera(); if (camera != NULL) { sceneNode->type = FbxString("camera"); sceneNode->attributes.push_back(std::make_pair(FbxString("name"), node->GetName())); sceneNode->attributes.push_back(std::make_pair(FbxString("fixed"), FbxString("true"))); FbxVector4 position = camera->EvaluatePosition(); FbxVector4 center = camera->EvaluateLookAtPosition(); // FIXME: seems EvaluateUpDirection doesn't give correct result as it // is affected by its parent nodes' tranforms however we attach camera // to the root in paper3d's scene. // FbxVector4 up = camera->EvaluateUpDirection(position, center); FbxDouble3 up = camera->UpVector.Get(); char buffer[1024]; FBXSDK_sprintf(buffer, 1024, "eye:%8.5f,%8.5f,%8.5f,center:%8.5f,%8.5f,%8.5f,up:%8.5f,%8.5f,%8.5f", (float)position[0], (float)position[1], (float)position[2], (float)center[0], (float)center[1], (float)center[2], (float)up[0], (float)up[1], (float)up[2]); sceneNode->attributes.push_back(std::make_pair(FbxString("lookat"), FbxString(buffer))); float nearZ = (float)camera->GetNearPlane(); float farZ = (float)camera->GetFarPlane(); if (camera->ProjectionType.Get() == FbxCamera::ePerspective) { FbxCamera::EAspectRatioMode lCamAspectRatioMode = camera->GetAspectRatioMode(); double lAspectX = camera->AspectWidth.Get(); double lAspectY = camera->AspectHeight.Get(); double lAspectRatio = 1.333333; switch( lCamAspectRatioMode) { case FbxCamera::eWindowSize: lAspectRatio = lAspectX / lAspectY; break; case FbxCamera::eFixedRatio: lAspectRatio = lAspectX; break; case FbxCamera::eFixedResolution: lAspectRatio = lAspectX / lAspectY * camera->GetPixelRatio(); break; case FbxCamera::eFixedWidth: lAspectRatio = camera->GetPixelRatio() / lAspectY; break; case FbxCamera::eFixedHeight: lAspectRatio = camera->GetPixelRatio() * lAspectX; break; default: break; } //get the aperture ratio double lFilmHeight = camera->GetApertureHeight(); double lFilmWidth = camera->GetApertureWidth() * camera->GetSqueezeRatio(); //here we use Height : Width double lApertureRatio = lFilmHeight / lFilmWidth; //change the aspect ratio to Height : Width lAspectRatio = 1 / lAspectRatio; //revise the aspect ratio and aperture ratio FbxCamera::EGateFit lCameraGateFit = camera->GateFit.Get(); switch( lCameraGateFit ) { case FbxCamera::eFitFill: if( lApertureRatio > lAspectRatio) // the same as eHORIZONTAL_FIT { lFilmHeight = lFilmWidth * lAspectRatio; camera->SetApertureHeight( lFilmHeight); lApertureRatio = lFilmHeight / lFilmWidth; } else if( lApertureRatio < lAspectRatio) //the same as eVERTICAL_FIT { lFilmWidth = lFilmHeight / lAspectRatio; camera->SetApertureWidth( lFilmWidth); lApertureRatio = lFilmHeight / lFilmWidth; } break; case FbxCamera::eFitVertical: lFilmWidth = lFilmHeight / lAspectRatio; camera->SetApertureWidth( lFilmWidth); lApertureRatio = lFilmHeight / lFilmWidth; break; case FbxCamera::eFitHorizontal: lFilmHeight = lFilmWidth * lAspectRatio; camera->SetApertureHeight( lFilmHeight); lApertureRatio = lFilmHeight / lFilmWidth; break; case FbxCamera::eFitStretch: lAspectRatio = lApertureRatio; break; case FbxCamera::eFitOverscan: if( lFilmWidth > lFilmHeight) { lFilmHeight = lFilmWidth * lAspectRatio; } else { lFilmWidth = lFilmHeight / lAspectRatio; } lApertureRatio = lFilmHeight / lFilmWidth; break; case FbxCamera::eFitNone: default: break; } //change the aspect ratio to Width : Height lAspectRatio = 1 / lAspectRatio; #define HFOV2VFOV(h, ar) (2.0 * atan((ar) * tan( (h * FBXSDK_PI_DIV_180) * 0.5)) * FBXSDK_180_DIV_PI) //ar : aspectY / aspectX #define VFOV2HFOV(v, ar) (2.0 * atan((ar) * tan( (v * FBXSDK_PI_DIV_180) * 0.5)) * FBXSDK_180_DIV_PI) //ar : aspectX / aspectY double lFieldOfViewX = 0.0; double lFieldOfViewY = 0.0; if (camera->GetApertureMode() == FbxCamera::eVertical) { lFieldOfViewY = camera->FieldOfView.Get(); lFieldOfViewX = VFOV2HFOV( lFieldOfViewY, 1 / lApertureRatio); } else if (camera->GetApertureMode() == FbxCamera::eHorizontal) { lFieldOfViewX = camera->FieldOfView.Get(); //get HFOV lFieldOfViewY = HFOV2VFOV( lFieldOfViewX, lApertureRatio); } else if (camera->GetApertureMode() == FbxCamera::eFocalLength) { lFieldOfViewX = camera->ComputeFieldOfView(camera->FocalLength.Get()); //get HFOV lFieldOfViewY = HFOV2VFOV( lFieldOfViewX, lApertureRatio); } else if (camera->GetApertureMode() == FbxCamera::eHorizAndVert) { lFieldOfViewX = camera->FieldOfViewX.Get(); lFieldOfViewY = camera->FieldOfViewY.Get(); } #undef HFOV2VFOV #undef VFOV2HFOV FBXSDK_sprintf(buffer, 1024, "perspective,fov:%8.5f,aspect:-1,znear:%8.5f,zfar:%8.5f", (float)lFieldOfViewY, nearZ, farZ); sceneNode->attributes.push_back(std::make_pair(FbxString("projection"), FbxString(buffer))); } else { FBXSDK_sprintf(buffer, 1024, "orthogonal,aspect:-1,znear:%8.5f,zfar:%8.5f", nearZ, farZ); sceneNode->attributes.push_back(std::make_pair(FbxString("projection"), FbxString(buffer))); } m_numCameras++; } else { FbxLight *light = node->GetLight(); if (light != NULL) { m_numLights++; FBX_ASSERT(!"Not implemented!"); } else { // Type sceneNode->type = FbxString("drawable"); // Name sceneNode->attributes.push_back(std::make_pair(FbxString("name"), node->GetName())); // Transformation FbxAMatrix m = node->EvaluateLocalTransform(); //FbxAMatrix m1 = node->EvaluateGlobalTransform(); const FbxVector4 translation = m.GetT(); const FbxVector4 rotation = m.GetR(); const FbxVector4 scaling = m.GetS(); float s[3], r[3], t[3]; t[0] = (float)translation.mData[0]; t[1] = (float)translation.mData[1]; t[2] = (float)translation.mData[2]; r[0] = (float)(rotation[0] * FBXSDK_DEG_TO_RAD); r[1] = (float)(rotation[1] * FBXSDK_DEG_TO_RAD); r[2] = (float)(rotation[2] * FBXSDK_DEG_TO_RAD); s[0] = (float)scaling[0]; s[1] = (float)scaling[1]; s[2] = (float)scaling[2]; //const FbxVector4 translation1 = m1.GetT(); //const FbxVector4 rotation1 = m1.GetR(); //const FbxVector4 scaling1 = m1.GetS(); char buffer[1024]; FBXSDK_sprintf(buffer, 1024, "s:%8.5f,%8.5f,%8.5f,r:%8.5f,%8.5f,%8.5f,t:%8.5f,%8.5f,%8.5f", s[0], s[1], s[2], r[0], r[1], r[2], t[0], t[1], t[2]); sceneNode->attributes.push_back(std::make_pair(FbxString("transform"), FbxString(buffer))); // Mesh //if (node->GetNodeAttribute()->GetAttributeType() == FbxNodeAttribute::eCamera) //{ // FBXSDK_printf("f**k"); //} static FbxUInt32 i = 0; if (node->GetMesh() == NULL) { sceneNode->type = FbxString("node"); } else { const char *meshName = node->GetMesh()->GetName(); if (meshName == NULL || meshName[0] == 0) { meshName = node->GetName(); } FbxString prefix; if (meshName == NULL || meshName[0] == 0) { prefix = FbxString("mesh_") + FbxString(int(i++)); } else { prefix = FbxString(meshName); } sceneNode->geometry = prefix + FbxString(".") + m_arguments->meshFormat; // Material FbxSurfaceMaterial *material = node->GetMaterial(0); if (material != NULL) { // This only gets the material of type sDiffuse, you probably need to // traverse all Standard Material Property by its name to get all // possible textures. FbxProperty prop = material->FindProperty(FbxSurfaceMaterial::sDiffuse); // Check if it's layeredtextures int layeredTextureCount = prop.GetSrcObjectCount<FbxLayeredTexture>(); if (prop.GetSrcObjectCount<FbxTexture>() > 0) { FbxFileTexture *lTex = prop.GetSrcObject<FbxFileTexture>(0); FbxString filename = FbxPathUtils::GetFileName(lTex->GetFileName()); sceneNode->texture = filename.Lower(); m_textures.push_back(FbxString(lTex->GetFileName())); } // root node is not counted as a drawable. m_numDrawables++; } } } } } return sceneNode; }