FbxDouble3 GetMaterialProperty(const FbxSurfaceMaterial * pMaterial, const char * pPropertyName, const char * pFactorPropertyName, std::string & pTextureName) { FbxDouble3 lResult(0, 0, 0); const FbxProperty lProperty = pMaterial->FindProperty(pPropertyName); const FbxProperty lFactorProperty = pMaterial->FindProperty(pFactorPropertyName); if (lProperty.IsValid() && lFactorProperty.IsValid()) { lResult = lProperty.Get<FbxDouble3>(); double lFactor = lFactorProperty.Get<FbxDouble>(); if (lFactor != 1) { lResult[0] *= lFactor; lResult[1] *= lFactor; lResult[2] *= lFactor; } } if (lProperty.IsValid()) { const int lTextureCount = lProperty.GetSrcObjectCount<FbxFileTexture>(); if (lTextureCount) { const FbxFileTexture* lTexture = lProperty.GetSrcObject<FbxFileTexture>(); if (lTexture) { pTextureName = lTexture->GetFileName(); } } } return lResult; }
// Bake material properties. bool MaterialCache::Initialize(const FbxSurfaceMaterial * pMaterial) { const FbxDouble3 lEmissive = GetMaterialProperty(pMaterial, FbxSurfaceMaterial::sEmissive, FbxSurfaceMaterial::sEmissiveFactor, mEmissive.mTextureName); mEmissive.mColor[0] = static_cast<GLfloat>(lEmissive[0]); mEmissive.mColor[1] = static_cast<GLfloat>(lEmissive[1]); mEmissive.mColor[2] = static_cast<GLfloat>(lEmissive[2]); const FbxDouble3 lAmbient = GetMaterialProperty(pMaterial, FbxSurfaceMaterial::sAmbient, FbxSurfaceMaterial::sAmbientFactor, mAmbient.mTextureName); mAmbient.mColor[0] = static_cast<GLfloat>(lAmbient[0]); mAmbient.mColor[1] = static_cast<GLfloat>(lAmbient[1]); mAmbient.mColor[2] = static_cast<GLfloat>(lAmbient[2]); const FbxDouble3 lDiffuse = GetMaterialProperty(pMaterial, FbxSurfaceMaterial::sDiffuse, FbxSurfaceMaterial::sDiffuseFactor, mDiffuse.mTextureName); mDiffuse.mColor[0] = static_cast<GLfloat>(lDiffuse[0]); mDiffuse.mColor[1] = static_cast<GLfloat>(lDiffuse[1]); mDiffuse.mColor[2] = static_cast<GLfloat>(lDiffuse[2]); const FbxDouble3 lSpecular = GetMaterialProperty(pMaterial, FbxSurfaceMaterial::sSpecular, FbxSurfaceMaterial::sSpecularFactor, mSpecular.mTextureName); mSpecular.mColor[0] = static_cast<GLfloat>(lSpecular[0]); mSpecular.mColor[1] = static_cast<GLfloat>(lSpecular[1]); mSpecular.mColor[2] = static_cast<GLfloat>(lSpecular[2]); FbxProperty lShininessProperty = pMaterial->FindProperty(FbxSurfaceMaterial::sShininess); if (lShininessProperty.IsValid()) { double lShininess = lShininessProperty.Get<FbxDouble>(); mShinness = static_cast<GLfloat>(lShininess); } return true; }
jdoubleArray getMaterialColorByProperty(JNIEnv *env, jint materialIndex, FbxDouble3 fbxColor, FbxDouble fbxColorFactor) { jdoubleArray color = env->NewDoubleArray(4); // Check memory could be allocated. if (color == NULL) { throwOutOfMemoryError(env); } FbxDouble transparencyFactor = ((FbxSurfaceLambert *) currentNode->GetMaterial(materialIndex))->TransparencyFactor; FbxDouble opacity; // Older FBX files may define the 'Opacity' property instead of 'TransparencyFactor'. FbxProperty opacityProperty = currentNode->GetMaterial(materialIndex)->FindProperty("Opacity"); if (opacityProperty.IsValid()) { opacity = opacityProperty.Get<FbxDouble>(); } else { opacity = 1-transparencyFactor; } double colorArray[4]; for (int i=0; i<3; i++) { colorArray[i] = fbxColorFactor*fbxColor[i]; } colorArray[3] = opacity; env->SetDoubleArrayRegion(color, 0, 4, colorArray); return color; }
void FBXImporter::LoadMaterialTexture(FBXMeshData* fbxMeshData, const char* textureType) { FbxProperty property; // #NoteReference to DisplayMesh.cxx in FBX SDK samples.Note# property = fbxMeshData->mSurfaceMaterial->FindProperty(textureType); if (property.IsValid()) { int textureCount = property.GetSrcObjectCount<FbxTexture>(); for (int i = 0; i < textureCount; i++) { FbxTexture* texture = FbxCast<FbxTexture>(property.GetSrcObject<FbxTexture>(i)); if (texture != nullptr) { FbxFileTexture* fileTexture = FbxCast<FbxFileTexture>(texture); string textureFileName = fileTexture->GetFileName(); if (strcmp(textureType, FbxSurfaceMaterial::sDiffuse) == 0) { fbxMeshData->mMaterial->setDiffuseTexture(textureFileName); } else if (strcmp(textureType, FbxSurfaceMaterial::sBump) == 0) { fbxMeshData->mMaterial->setNormalMapTexture(textureFileName); } } } } }
void CFBXLoader::CopyMatrialData(FbxSurfaceMaterial* mat, FBX_MATERIAL_NODE* destMat) { if(!mat) return ; if ( mat->GetClassId().Is( FbxSurfaceLambert::ClassId ) ) { destMat->type = FBX_MATERIAL_NODE::MATERIAL_LAMBERT; } else if ( mat->GetClassId().Is( FbxSurfacePhong::ClassId ) ) { destMat->type = FBX_MATERIAL_NODE::MATERIAL_PHONG; } const FbxDouble3 lEmissive = GetMaterialProperty(mat, FbxSurfaceMaterial::sEmissive, FbxSurfaceMaterial::sEmissiveFactor, &destMat->emmisive); SetFbxColor(destMat->emmisive, lEmissive ); const FbxDouble3 lAmbient = GetMaterialProperty(mat, FbxSurfaceMaterial::sAmbient, FbxSurfaceMaterial::sAmbientFactor, &destMat->ambient); SetFbxColor(destMat->ambient, lAmbient ); const FbxDouble3 lDiffuse = GetMaterialProperty(mat, FbxSurfaceMaterial::sDiffuse, FbxSurfaceMaterial::sDiffuseFactor, &destMat->diffuse); SetFbxColor(destMat->diffuse, lDiffuse ); const FbxDouble3 lSpecular = GetMaterialProperty(mat, FbxSurfaceMaterial::sSpecular, FbxSurfaceMaterial::sSpecularFactor, &destMat->specular); SetFbxColor(destMat->specular, lSpecular ); // FbxProperty lTransparencyFactorProperty = mat->FindProperty(FbxSurfaceMaterial::sTransparencyFactor); if(lTransparencyFactorProperty.IsValid()) { double lTransparencyFactor = lTransparencyFactorProperty.Get<FbxDouble>(); destMat->TransparencyFactor = static_cast<float>(lTransparencyFactor); } // Specular Power FbxProperty lShininessProperty = mat->FindProperty(FbxSurfaceMaterial::sShininess); if (lShininessProperty.IsValid()) { double lShininess = lShininessProperty.Get<FbxDouble>(); destMat->shininess = static_cast<float>(lShininess); } }
// マテリアル表示 void GetMatrialData(FbxSurfaceMaterial* mat) { if(mat == nullptr) { return; } puts(""); if(mat->GetClassId().Is(FbxSurfaceLambert::ClassId)) { printf("ランバートタイプ\n"); } else if(mat->GetClassId().Is(FbxSurfacePhong::ClassId)) { printf("フォンタイプ\n"); } const FbxDouble3 lEmissive = GetMaterialProperty(mat, FbxSurfaceMaterial::sEmissive, FbxSurfaceMaterial::sEmissiveFactor); printf("エミッシブカラー:r = %f, g = %f, b = %f\n", lEmissive.mData[0], lEmissive.mData[1], lEmissive.mData[2]); const FbxDouble3 lAmbient = GetMaterialProperty(mat, FbxSurfaceMaterial::sAmbient, FbxSurfaceMaterial::sAmbientFactor); printf("アンビエントカラー:r = %f, g = %f, b = %f\n", lAmbient.mData[0], lAmbient.mData[1], lAmbient.mData[2]); const FbxDouble3 lDiffuse = GetMaterialProperty(mat, FbxSurfaceMaterial::sDiffuse, FbxSurfaceMaterial::sDiffuseFactor); printf("ディフューズカラー:r = %f, g = %f, b = %f\n", lDiffuse.mData[0], lDiffuse.mData[1], lDiffuse.mData[2]); const FbxDouble3 lSpecular = GetMaterialProperty(mat, FbxSurfaceMaterial::sSpecular, FbxSurfaceMaterial::sSpecularFactor); printf("スペキュラカラー:r = %f, g = %f, b = %f\n", lSpecular.mData[0], lSpecular.mData[1], lSpecular.mData[2]); FbxProperty lTransparencyFactorProperty = mat->FindProperty(FbxSurfaceMaterial::sTransparencyFactor); if(lTransparencyFactorProperty.IsValid()) { double lTransparencyFactor = lTransparencyFactorProperty.Get<FbxDouble>(); printf("透明度 = %lf\n", lTransparencyFactor); } FbxProperty lShininessProperty = mat->FindProperty(FbxSurfaceMaterial::sShininess); if(lShininessProperty.IsValid()) { double lShininess = lShininessProperty.Get<FbxDouble>(); printf("スペキュラ = %lf\n", lShininess); } }
void FbxLoader::FbxLoader::ProcessMaterialTexture2D(FbxSurfaceMaterial* mat, FMaterial& material) { int Texture2DIndex = 0; FbxProperty prop; FBXSDK_FOR_EACH_TEXTURE(Texture2DIndex) { prop = mat->FindProperty(FbxLayerElement::sTextureChannelNames[Texture2DIndex]); if(prop.IsValid()) { const int Texture2DCount = prop.GetSrcObjectCount<FbxTexture>(); for(int i = 0; i < Texture2DCount; i++) { FbxTexture* texture = prop.GetSrcObject<FbxTexture>(i); if(texture) { std::string textureType = prop.GetNameAsCStr(); FbxFileTexture* fileTexture = FbxCast<FbxFileTexture>(texture); if(fileTexture) { if(textureType == "DiffuseColor") material.diffuseMapName = fileTexture->GetRelativeFileName(); else if(textureType == "SpecularColor") material.specularMapName = fileTexture->GetRelativeFileName(); else if(textureType == "NormalMap") { material.normalMapName = fileTexture->GetRelativeFileName(); useNormalMap = true; } } } } const int layeredTextureCount = prop.GetSrcObjectCount<FbxLayeredTexture>(); for(int i = 0; i < layeredTextureCount; i++) { auto layeredTexture = prop.GetSrcObject<FbxLayeredTexture>(i); const int fileCount = layeredTexture->GetSrcObjectCount<FbxFileTexture>(); for(int j = 0; j < fileCount; j++) { auto fileTexture = layeredTexture->GetSrcObject<FbxFileTexture>(j); std::string Texture2DType = prop.GetNameAsCStr(); if(fileTexture) { if(Texture2DType == "DiffuseColor") material.diffuseMapName = fileTexture->GetRelativeFileName(); else if(Texture2DType == "SpecularColor") material.specularMapName = fileTexture->GetRelativeFileName(); else if(Texture2DType == "NormalMap") { material.normalMapName = fileTexture->GetRelativeFileName(); useNormalMap = true; } } } } } } if(material.diffuseMapName != "") { std::string n = FbxPathUtils::GetFileName(material.diffuseMapName.c_str(), false).Buffer(); material.name = n; mat->SetName(n.c_str()); } }
void FBXSceneEncoder::loadMaterialTextures(FbxSurfaceMaterial* fbxMaterial, Material* material) { FbxProperty fbxProperty; int textureIndex; FBXSDK_FOR_EACH_TEXTURE(textureIndex) { fbxProperty = fbxMaterial->FindProperty(FbxLayerElement::sTextureChannelNames[textureIndex]); //FindAndDisplayTextureInfoByProperty(fbxProperty, lDisplayHeader, lMaterialIndex); if ( fbxProperty.IsValid() ) { int textureCount = fbxProperty.GetSrcObjectCount<FbxTexture>(); for (int j = 0; j < textureCount; ++j) { FbxLayeredTexture *layeredTexture = fbxProperty.GetSrcObject<FbxLayeredTexture>(j); if (layeredTexture) { //DisplayInt(" Layered Texture: ", j); FbxLayeredTexture *layeredTexture = fbxProperty.GetSrcObject<FbxLayeredTexture>(j); int lNbTextures = layeredTexture->GetSrcObjectCount<FbxTexture>(); for (int k = 0; k<lNbTextures; ++k) { FbxTexture* fbxTexture = layeredTexture->GetSrcObject<FbxTexture>(k); if (fbxTexture) { /* if (pDisplayHeader){ DisplayInt(" Textures connected to Material ", pMaterialIndex); pDisplayHeader = false; } */ //NOTE the blend mode is ALWAYS on the LayeredTexture and NOT the one on the texture. //Why is that? because one texture can be shared on different layered textures and might //have different blend modes. FbxLayeredTexture::EBlendMode lBlendMode; layeredTexture->GetTextureBlendMode(k, lBlendMode); //DisplayString(" Textures for ", pProperty.GetName()); //DisplayInt(" Texture ", k); //DisplayTextureInfo(fbxTexture, (int) lBlendMode); } } } else if (FbxTexture* fbxTexture = fbxProperty.GetSrcObject<FbxTexture>(j)) { //no layered texture simply get on the property if (FbxFileTexture* fileTexture = FbxCast<FbxFileTexture>(fbxTexture)) { loadMaterialFileTexture(fileTexture, material); } } } } } }
static void GetCustomVisionData(FbxNode* fbxNode, hkStringPtr& userPropertiesStr) { userPropertiesStr = ""; for(FbxProperty prop = fbxNode->GetFirstProperty(); prop.IsValid(); prop = fbxNode->GetNextProperty(prop)) { EFbxType type = prop.GetPropertyDataType().GetType(); if (type == eFbxString) { FbxString propertyData = prop.Get<FbxString>(); const char* text = propertyData.Buffer(); if (!hkString::strNcasecmp(text, "vision", 6)) { userPropertiesStr = text; break; } } } }
void Converter::getDiffuseTextures(FbxSurfaceMaterial *material, std::vector<std::string> &textures) { FbxProperty property = material->FindProperty(FbxLayerElement::sTextureChannelNames[0]); if (property.IsValid()) { for (int j = 0; j < property.GetSrcObjectCount<FbxTexture>(); ++j) { if (!property.GetSrcObject<FbxLayeredTexture>(j)) { FbxTexture* texture = property.GetSrcObject<FbxTexture>(j); if (texture) { std::string textureType = property.GetNameAsCStr(); FbxFileTexture* fileTexture = FbxCast<FbxFileTexture>(texture); if (fileTexture) { if (textureType == "DiffuseColor") { //std::cout << fileTexture->GetRelativeFileName() << "\n"; textures.push_back(fileTexture->GetRelativeFileName()); } } } } } } }
Material *FBX::buildMaterialFromFBX(FbxSurfaceMaterial *lMaterial) { Material *material=new Material(lMaterial->GetName()); material->setShader("Common_d"); material->addParameter(new Parameter("diffuse", Color(1.0, 1.0, 1.0, 0.0))); material->addParameter(new Parameter("ambient", Color(1.0, 1.0, 1.0, 0.0))); material->addParameter(new Parameter("specular", Color(0.9, 0.9, 0.9, 0.0))); material->addParameter(new Parameter("emissive", Color(0.0, 0.0, 0.0, 0.0))); material->addParameter(new Parameter("power_gloss_level", Color(50.0, 0.1, 0.0, 0.0))); material->addParameter(new Parameter("opacity_reflection_refraction_spectype", Color(1.0, 0.0, 1.0, 0.0))); material->addParameter(new Parameter("", Color(0.0, 0.0, 0.0, 0.0))); material->addParameter(new Parameter("", Color(0.0, 0.0, 0.0, 0.0))); material->addParameter(new Parameter("", Color(0.0, 0.0, 0.0, 0.0))); material->addParameter(new Parameter("", Color(0.0, 0.0, 0.0, 0.0))); FbxProperty lProperty = lMaterial->FindProperty(FbxSurfaceMaterial::sDiffuse); if (lProperty.IsValid()) { const int lTextureCount = lProperty.GetSrcObjectCount<FbxFileTexture>(); if (lTextureCount) { const FbxFileTexture* lTexture = lProperty.GetSrcObject<FbxFileTexture>(); if (lTexture) { string path=ToString(lTexture->GetFileName()); size_t sep = path.find_last_of("\\/"); if (sep != std::string::npos) { path = path.substr(sep + 1, path.size() - sep - 1); } size_t dot = path.find_last_of("."); if (dot != string::npos) { path = path.substr(0, dot); } Texture *texture=new Texture(ToString(lMaterial->GetName())+"-0000", "diffuse", path); material->addTextureUnit(texture); } } } return material; }
//------------------------------------------------------------------------------------------------------------------------------------------- void transferTextureByProperty(FbxProperty fbxProperty, int matId, Material* modelMaterial){ if (fbxProperty.IsValid()){ int textureCount = fbxProperty.GetSrcObjectCount<FbxTexture>(); for (int texId = 0; texId < textureCount; texId++){ FbxLayeredTexture* layeredTexture = fbxProperty.GetSrcObject<FbxLayeredTexture>(texId); if (layeredTexture){ int numTexture = layeredTexture->GetSrcObjectCount<FbxTexture>(); for (int k = 0; k < numTexture; k++){ FbxTexture* texture = layeredTexture->GetSrcObject<FbxTexture>(k); if (texture){ LOG_DEBUG << " Textures connected to material " << matId; Texture* modelTexture = new Texture(); FbxLayeredTexture::EBlendMode blendMode; layeredTexture->GetTextureBlendMode(k, blendMode); transferTextureInfo(texture, (int)blendMode, modelTexture); modelMaterial->Textures.push_back(modelTexture); } } } else { // There is no layered texture FbxTexture* texture = fbxProperty.GetSrcObject<FbxTexture>(texId); if (texture){ LOG_DEBUG << " Textures connected to material " << matId; Texture* modelTexture = new Texture(); transferTextureInfo(texture, -1, modelTexture); modelMaterial->Textures.push_back(modelTexture); } } } } }
StateSetContent FbxMaterialToOsgStateSet::convert(const FbxSurfaceMaterial* pFbxMat) { FbxMaterialMap::const_iterator it = _fbxMaterialMap.find(pFbxMat); if (it != _fbxMaterialMap.end()) return it->second; osg::ref_ptr<osg::Material> pOsgMat = new osg::Material; pOsgMat->setName(pFbxMat->GetName()); StateSetContent result; result.material = pOsgMat; FbxString shadingModel = pFbxMat->ShadingModel.Get(); const FbxSurfaceLambert* pFbxLambert = FbxCast<FbxSurfaceLambert>(pFbxMat); // diffuse map... result.diffuse = selectTextureDetails(pFbxMat->FindProperty(FbxSurfaceMaterial::sDiffuse)); // opacity map... double transparencyColorFactor = 1.0; bool useTransparencyColorFactor = false; const FbxProperty lOpacityProperty = pFbxMat->FindProperty(FbxSurfaceMaterial::sTransparentColor); if (lOpacityProperty.IsValid()) { FbxDouble3 transparentColor = lOpacityProperty.Get<FbxDouble3>(); // If transparent color is defined set the transparentFactor to gray scale value of transparentColor if (transparentColor[0] < 1.0 || transparentColor[1] < 1.0 || transparentColor[2] < 1.0) { transparencyColorFactor = transparentColor[0]*0.30 + transparentColor[1]*0.59 + transparentColor[2]*0.11; useTransparencyColorFactor = true; } result.opacity = selectTextureDetails(lOpacityProperty); } // reflection map... result.reflection = selectTextureDetails(pFbxMat->FindProperty(FbxSurfaceMaterial::sReflection)); // emissive map... result.emissive = selectTextureDetails(pFbxMat->FindProperty(FbxSurfaceMaterial::sEmissive)); // ambient map... result.ambient = selectTextureDetails(pFbxMat->FindProperty(FbxSurfaceMaterial::sAmbient)); // normal map... result.normalMap = selectTextureDetails(pFbxMat->FindProperty(FbxSurfaceMaterial::sNormalMap)); // specular map... result.specular = selectTextureDetails(pFbxMat->FindProperty(FbxSurfaceMaterial::sSpecular)); // shininess map... result.shininess = selectTextureDetails(pFbxMat->FindProperty(FbxSurfaceMaterial::sShininess)); if (pFbxLambert) { FbxDouble3 color = pFbxLambert->Diffuse.Get(); double factor = pFbxLambert->DiffuseFactor.Get(); double transparencyFactor = useTransparencyColorFactor ? transparencyColorFactor : pFbxLambert->TransparencyFactor.Get(); pOsgMat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4( static_cast<float>(color[0] * factor), static_cast<float>(color[1] * factor), static_cast<float>(color[2] * factor), static_cast<float>(1.0 - transparencyFactor))); color = pFbxLambert->Ambient.Get(); factor = pFbxLambert->AmbientFactor.Get(); pOsgMat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4( static_cast<float>(color[0] * factor), static_cast<float>(color[1] * factor), static_cast<float>(color[2] * factor), 1.0f)); color = pFbxLambert->Emissive.Get(); factor = pFbxLambert->EmissiveFactor.Get(); pOsgMat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4( static_cast<float>(color[0] * factor), static_cast<float>(color[1] * factor), static_cast<float>(color[2] * factor), 1.0f)); // get maps factors... if (result.diffuse.valid()) result.diffuse->factor = pFbxLambert->DiffuseFactor.Get(); if (result.emissive.valid()) result.emissive->factor = pFbxLambert->EmissiveFactor.Get(); if (result.ambient.valid()) result.ambient->factor = pFbxLambert->AmbientFactor.Get(); if (result.normalMap.valid()) result.normalMap->factor = pFbxLambert->BumpFactor.Get(); if (const FbxSurfacePhong* pFbxPhong = FbxCast<FbxSurfacePhong>(pFbxLambert)) { color = pFbxPhong->Specular.Get(); factor = pFbxPhong->SpecularFactor.Get(); pOsgMat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4( static_cast<float>(color[0] * factor), static_cast<float>(color[1] * factor), static_cast<float>(color[2] * factor), 1.0f)); // Since Maya and 3D studio Max stores their glossiness values in exponential format (2^(log2(x)) // We need to linearize to values between 0-100 and then scale to values between 0-128. // Glossiness values above 100 will result in shininess larger than 128.0 and will be clamped double shininess = (64.0 * log (pFbxPhong->Shininess.Get())) / (5.0 * log(2.0)); pOsgMat->setShininess(osg::Material::FRONT_AND_BACK, static_cast<float>(shininess)); // get maps factors... if (result.reflection.valid()) result.reflection->factor = pFbxPhong->ReflectionFactor.Get(); if (result.specular.valid()) result.specular->factor = pFbxPhong->SpecularFactor.Get(); // get more factors here... } } if (_lightmapTextures) { // if using an emission map then adjust material properties accordingly... if (result.emissive.valid()) { osg::Vec4 diffuse = pOsgMat->getDiffuse(osg::Material::FRONT_AND_BACK); pOsgMat->setEmission(osg::Material::FRONT_AND_BACK, diffuse); pOsgMat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0,0,0,diffuse.a())); pOsgMat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0,0,0,diffuse.a())); } } _fbxMaterialMap.insert(FbxMaterialMap::value_type(pFbxMat, result)); return result; }
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() ); } } }
void Tools::DisplayGenericInfo::DisplayProperties( FbxObject *i_object ) { DisplayCommon::DisplayString( "Name: ", (char *)i_object->GetName() ); // Display all the properties int i, count = 0; FbxProperty lProperty = i_object->GetFirstProperty(); while( lProperty.IsValid() ) { count++; lProperty = i_object->GetNextProperty( lProperty ); } FbxString lTitleStr = " Property Count: "; if( count == 0 ) return; // there are no properties to display DisplayCommon::DisplayInt( lTitleStr.Buffer(), count ); i = 0; lProperty = i_object->GetFirstProperty(); while( lProperty.IsValid() ) { // exclude user properties FbxString string; DisplayCommon::DisplayInt( " Property ", i ); string = lProperty.GetLabel(); DisplayCommon::DisplayString( " Display Name: ", string ); string = lProperty.GetName(); DisplayCommon::DisplayString( " Internal Name: ", string.Buffer() ); string = lProperty.GetPropertyDataType().GetName(); DisplayCommon::DisplayString( " Type: ",string.Buffer() ); if (lProperty.HasMinLimit()) DisplayCommon::DisplayDouble( " Min Limit: ", lProperty.GetMinLimit() ); if (lProperty.HasMaxLimit()) DisplayCommon::DisplayDouble( " Max Limit: ", lProperty.GetMaxLimit() ); DisplayCommon::DisplayBool( " Is Animatable: ", lProperty.GetFlag(FbxPropertyAttr::eAnimatable) ); switch( lProperty.GetPropertyDataType().GetType() ) { case eFbxBool: DisplayCommon::DisplayBool( " Default Value: ", lProperty.Get<FbxBool>() ); break; case eFbxDouble: DisplayCommon::DisplayDouble( " Default Value: ", lProperty.Get<FbxDouble>() ); break; case eFbxDouble4: { FbxColor lDefault; char buffer[64]; lDefault = lProperty.Get<FbxColor>(); FBXSDK_sprintf( buffer, 64, "R=%f, G=%f, B=%f, A=%f", lDefault.mRed, lDefault.mGreen, lDefault.mBlue, lDefault.mAlpha ); DisplayCommon::DisplayString( " Default Value: ", buffer ); } break; case eFbxInt: DisplayCommon::DisplayInt( " Default Value: ", lProperty.Get<FbxInt>() ); break; case eFbxDouble3: { FbxDouble3 lDefault; char buffer[64]; lDefault = lProperty.Get<FbxDouble3>(); FBXSDK_sprintf( buffer, 64, "X=%f, Y=%f, Z=%f", lDefault[0], lDefault[1], lDefault[2] ); DisplayCommon::DisplayString( " Default Value: ", buffer ); } break; //case FbxEnumDT: // DisplayInt(" Default Value: ", lProperty.Get<FbxEnum>()); // break; case eFbxFloat: DisplayCommon::DisplayDouble( " Default Value: ", lProperty.Get<FbxFloat>() ); break; case eFbxString: string = lProperty.Get<FbxString>(); DisplayCommon::DisplayString( " Default Value: ", string.Buffer() ); break; default: DisplayCommon::DisplayString( " Default Value: UNIDENTIFIED" ); break; } i++; lProperty = i_object->GetNextProperty( lProperty ); } }
void FbxMaterial::AddProperty(const FbxProperty &property, const FbxProperty &factor_property) { /** *If we are dealing with an invalid properties, abort */ if (!property.IsValid() || !factor_property.IsValid()) return; /** *Get the name of the property */ QString property_name = property.GetNameAsCStr(); /** *Based on the property's name, load required stuff */ if (property_name == FbxSurfaceMaterial::sDiffuse) { /** *Get the diffuse color and intensity */ FbxDouble3 diffuse_color = property.Get<FbxDouble3>(); FbxDouble diffuse_intensity = factor_property.Get<FbxDouble>(); /** *Set diffuse color and intensity */ SetDiffuseColor(aae::mesh_util::QVector3DFromFbxVector3D(diffuse_color)); SetDiffuseIntensity(diffuse_intensity); /** *If there are no textures attached to the property, return */ if(!property.GetSrcObjectCount<FbxFileTexture>() > 0) return; /** *Get the texture handler */ FbxFileTexture * texture = property.GetSrcObject<FbxFileTexture>(); if (!texture) return; /** *Add the diffuse texture name of the material */ AddTexture(diffuse, texture->GetFileName()); } else if (property_name == FbxSurfaceMaterial::sNormalMap) { /** *If there are no textures attached to the property, return */ if(!property.GetSrcObjectCount<FbxFileTexture>() > 0) return; /** *Get the texture handler */ FbxFileTexture * texture = property.GetSrcObject<FbxFileTexture>(); if (!texture) return; /** *Set normal map texture of the material */ AddTexture(normal, texture->GetFileName()); } else if (property_name == FbxSurfaceMaterial::sSpecular) { /** *Get the specular color and intensity */ FbxDouble3 specular_color = property.Get<FbxDouble3>(); FbxDouble specular_intensity = factor_property.Get<FbxDouble>(); /** *Set the specular color and intensity */ SetSpecularColor(aae::mesh_util::QVector3DFromFbxVector3D(specular_color)); SetSpecularIntensity(specular_intensity); } else if (property_name == FbxSurfaceMaterial::sShininess) { /** *Get and set specular hardness */ FbxDouble specular_hardness = property.Get<FbxDouble>(); SetSpecularHardness(specular_hardness); } }
StateSetContent FbxMaterialToOsgStateSet::convert(const FbxSurfaceMaterial* pFbxMat) { FbxMaterialMap::const_iterator it = _fbxMaterialMap.find(pFbxMat); if (it != _fbxMaterialMap.end()) return it->second; osg::ref_ptr<osg::Material> pOsgMat = new osg::Material; pOsgMat->setName(pFbxMat->GetName()); StateSetContent result; result.material = pOsgMat; FbxString shadingModel = pFbxMat->ShadingModel.Get(); const FbxSurfaceLambert* pFbxLambert = FbxCast<FbxSurfaceLambert>(pFbxMat); // diffuse map... const FbxProperty lProperty = pFbxMat->FindProperty(FbxSurfaceMaterial::sDiffuse); if (lProperty.IsValid()) { int lNbTex = lProperty.GetSrcObjectCount<FbxFileTexture>(); for (int lTextureIndex = 0; lTextureIndex < lNbTex; lTextureIndex++) { FbxFileTexture* lTexture = FbxCast<FbxFileTexture>(lProperty.GetSrcObject<FbxFileTexture>(lTextureIndex)); if (lTexture) { result.diffuseTexture = fbxTextureToOsgTexture(lTexture); result.diffuseChannel = lTexture->UVSet.Get(); result.diffuseScaleU = lTexture->GetScaleU(); result.diffuseScaleV = lTexture->GetScaleV(); } //For now only allow 1 texture break; } } double transparencyColorFactor = 1.0; bool useTransparencyColorFactor = false; // opacity map... const FbxProperty lOpacityProperty = pFbxMat->FindProperty(FbxSurfaceMaterial::sTransparentColor); if (lOpacityProperty.IsValid()) { FbxDouble3 transparentColor = lOpacityProperty.Get<FbxDouble3>(); // If transparent color is defined set the transparentFactor to gray scale value of transparentColor if (transparentColor[0] < 1.0 || transparentColor[1] < 1.0 || transparentColor[2] < 1.0) { transparencyColorFactor = transparentColor[0]*0.30 + transparentColor[1]*0.59 + transparentColor[2]*0.11; useTransparencyColorFactor = true; } int lNbTex = lOpacityProperty.GetSrcObjectCount<FbxFileTexture>(); for (int lTextureIndex = 0; lTextureIndex < lNbTex; lTextureIndex++) { FbxFileTexture* lTexture = FbxCast<FbxFileTexture>(lOpacityProperty.GetSrcObject<FbxFileTexture>(lTextureIndex)); if (lTexture) { // TODO: if texture image does NOT have an alpha channel, should it be added? result.opacityTexture = fbxTextureToOsgTexture(lTexture); result.opacityChannel = lTexture->UVSet.Get(); result.opacityScaleU = lTexture->GetScaleU(); result.opacityScaleV = lTexture->GetScaleV(); } //For now only allow 1 texture break; } } // reflection map... const FbxProperty lReflectionProperty = pFbxMat->FindProperty(FbxSurfaceMaterial::sReflection); if (lReflectionProperty.IsValid()) { int lNbTex = lReflectionProperty.GetSrcObjectCount<FbxFileTexture>(); for (int lTextureIndex = 0; lTextureIndex < lNbTex; lTextureIndex++) { FbxFileTexture* lTexture = FbxCast<FbxFileTexture>(lReflectionProperty.GetSrcObject<FbxFileTexture>(lTextureIndex)); if (lTexture) { // support only spherical reflection maps... if (FbxFileTexture::eUMT_ENVIRONMENT == lTexture->CurrentMappingType.Get()) { result.reflectionTexture = fbxTextureToOsgTexture(lTexture); result.reflectionChannel = lTexture->UVSet.Get(); } } //For now only allow 1 texture break; } } // emissive map... const FbxProperty lEmissiveProperty = pFbxMat->FindProperty(FbxSurfaceMaterial::sEmissive); if (lEmissiveProperty.IsValid()) { int lNbTex = lEmissiveProperty.GetSrcObjectCount<FbxFileTexture>(); for (int lTextureIndex = 0; lTextureIndex < lNbTex; lTextureIndex++) { FbxFileTexture* lTexture = FbxCast<FbxFileTexture>(lEmissiveProperty.GetSrcObject<FbxFileTexture>(lTextureIndex)); if (lTexture) { result.emissiveTexture = fbxTextureToOsgTexture(lTexture); result.emissiveChannel = lTexture->UVSet.Get(); result.emissiveScaleU = lTexture->GetScaleU(); result.emissiveScaleV = lTexture->GetScaleV(); } //For now only allow 1 texture break; } } // ambient map... const FbxProperty lAmbientProperty = pFbxMat->FindProperty(FbxSurfaceMaterial::sAmbient); if (lAmbientProperty.IsValid()) { int lNbTex = lAmbientProperty.GetSrcObjectCount<FbxFileTexture>(); for (int lTextureIndex = 0; lTextureIndex < lNbTex; lTextureIndex++) { FbxFileTexture* lTexture = FbxCast<FbxFileTexture>(lAmbientProperty.GetSrcObject<FbxFileTexture>(lTextureIndex)); if (lTexture) { result.ambientTexture = fbxTextureToOsgTexture(lTexture); result.ambientChannel = lTexture->UVSet.Get(); result.ambientScaleU = lTexture->GetScaleU(); result.ambientScaleV = lTexture->GetScaleV(); } //For now only allow 1 texture break; } } if (pFbxLambert) { FbxDouble3 color = pFbxLambert->Diffuse.Get(); double factor = pFbxLambert->DiffuseFactor.Get(); double transparencyFactor = useTransparencyColorFactor ? transparencyColorFactor : pFbxLambert->TransparencyFactor.Get(); pOsgMat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4( static_cast<float>(color[0] * factor), static_cast<float>(color[1] * factor), static_cast<float>(color[2] * factor), static_cast<float>(1.0 - transparencyFactor))); color = pFbxLambert->Ambient.Get(); factor = pFbxLambert->AmbientFactor.Get(); pOsgMat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4( static_cast<float>(color[0] * factor), static_cast<float>(color[1] * factor), static_cast<float>(color[2] * factor), 1.0f)); color = pFbxLambert->Emissive.Get(); factor = pFbxLambert->EmissiveFactor.Get(); pOsgMat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4( static_cast<float>(color[0] * factor), static_cast<float>(color[1] * factor), static_cast<float>(color[2] * factor), 1.0f)); // get maps factors... result.diffuseFactor = pFbxLambert->DiffuseFactor.Get(); if (const FbxSurfacePhong* pFbxPhong = FbxCast<FbxSurfacePhong>(pFbxLambert)) { color = pFbxPhong->Specular.Get(); factor = pFbxPhong->SpecularFactor.Get(); pOsgMat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4( static_cast<float>(color[0] * factor), static_cast<float>(color[1] * factor), static_cast<float>(color[2] * factor), 1.0f)); // Since Maya and 3D studio Max stores their glossiness values in exponential format (2^(log2(x)) // We need to linearize to values between 0-100 and then scale to values between 0-128. // Glossiness values above 100 will result in shininess larger than 128.0 and will be clamped double shininess = (64.0 * log (pFbxPhong->Shininess.Get())) / (5.0 * log(2.0)); pOsgMat->setShininess(osg::Material::FRONT_AND_BACK, static_cast<float>(shininess)); // get maps factors... result.reflectionFactor = pFbxPhong->ReflectionFactor.Get(); // get more factors here... } } if (_lightmapTextures) { // if using an emission map then adjust material properties accordingly... if (result.emissiveTexture) { osg::Vec4 diffuse = pOsgMat->getDiffuse(osg::Material::FRONT_AND_BACK); pOsgMat->setEmission(osg::Material::FRONT_AND_BACK, diffuse); pOsgMat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0,0,0,diffuse.a())); pOsgMat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0,0,0,diffuse.a())); } } _fbxMaterialMap.insert(FbxMaterialMap::value_type(pFbxMat, result)); return result; }
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 }
bool UnFbx::FFbxImporter::ImportAnimation(USkeleton* Skeleton, UAnimSequence * DestSeq, const FString& FileName, TArray<FbxNode*>& SortedLinks, TArray<FbxNode*>& NodeArray, FbxAnimStack* CurAnimStack, const int32 ResampleRate, const FbxTimeSpan AnimTimeSpan) { // @todo : the length might need to change w.r.t. sampling keys FbxTime SequenceLength = AnimTimeSpan.GetDuration(); float PreviousSequenceLength = DestSeq->SequenceLength; // if you have one pose(thus 0.f duration), it still contains animation, so we'll need to consider that as MINIMUM_ANIMATION_LENGTH time length DestSeq->SequenceLength = FGenericPlatformMath::Max<float>(SequenceLength.GetSecondDouble(), MINIMUM_ANIMATION_LENGTH); if(PreviousSequenceLength > MINIMUM_ANIMATION_LENGTH && DestSeq->RawCurveData.FloatCurves.Num() > 0) { // The sequence already existed when we began the import. We need to scale the key times for all curves to match the new // duration before importing over them. This is to catch any user-added curves float ScaleFactor = DestSeq->SequenceLength / PreviousSequenceLength; for(FFloatCurve& Curve : DestSeq->RawCurveData.FloatCurves) { Curve.FloatCurve.ScaleCurve(0.0f, ScaleFactor); } } if (ImportOptions->bDeleteExistingMorphTargetCurves) { for (int32 CurveIdx=0; CurveIdx<DestSeq->RawCurveData.FloatCurves.Num(); ++CurveIdx) { auto& Curve = DestSeq->RawCurveData.FloatCurves[CurveIdx]; if (Curve.GetCurveTypeFlag(ACF_DrivesMorphTarget)) { DestSeq->RawCurveData.FloatCurves.RemoveAt(CurveIdx, 1, false); --CurveIdx; } } DestSeq->RawCurveData.FloatCurves.Shrink(); } // // import blend shape curves // { GWarn->BeginSlowTask( LOCTEXT("BeginImportMorphTargetCurves", "Importing Morph Target Curves"), true); for ( int32 NodeIndex = 0; NodeIndex < NodeArray.Num(); NodeIndex++ ) { // consider blendshape animation curve FbxGeometry* Geometry = (FbxGeometry*)NodeArray[NodeIndex]->GetNodeAttribute(); if (Geometry) { int32 BlendShapeDeformerCount = Geometry->GetDeformerCount(FbxDeformer::eBlendShape); for(int32 BlendShapeIndex = 0; BlendShapeIndex<BlendShapeDeformerCount; ++BlendShapeIndex) { FbxBlendShape* BlendShape = (FbxBlendShape*)Geometry->GetDeformer(BlendShapeIndex, FbxDeformer::eBlendShape); const int32 BlendShapeChannelCount = BlendShape->GetBlendShapeChannelCount(); FString BlendShapeName = UTF8_TO_TCHAR(MakeName(BlendShape->GetName())); for(int32 ChannelIndex = 0; ChannelIndex<BlendShapeChannelCount; ++ChannelIndex) { FbxBlendShapeChannel* Channel = BlendShape->GetBlendShapeChannel(ChannelIndex); if(Channel) { FString ChannelName = UTF8_TO_TCHAR(MakeName(Channel->GetName())); // Maya adds the name of the blendshape and an underscore to the front of the channel name, so remove it if(ChannelName.StartsWith(BlendShapeName)) { ChannelName = ChannelName.Right(ChannelName.Len() - (BlendShapeName.Len()+1)); } FbxAnimCurve* Curve = Geometry->GetShapeChannel(BlendShapeIndex, ChannelIndex, (FbxAnimLayer*)CurAnimStack->GetMember(0)); if (Curve && Curve->KeyGetCount() > 0) { FFormatNamedArguments Args; Args.Add(TEXT("BlendShape"), FText::FromString(ChannelName)); const FText StatusUpate = FText::Format(LOCTEXT("ImportingMorphTargetCurvesDetail", "Importing Morph Target Curves [{BlendShape}]"), Args); GWarn->StatusUpdate(NodeIndex + 1, NodeArray.Num(), StatusUpate); // now see if we have one already exists. If so, just overwrite that. if not, add new one. ImportCurveToAnimSequence(DestSeq, *ChannelName, Curve, ACF_DrivesMorphTarget | ACF_TriggerEvent, AnimTimeSpan, 0.01f /** for some reason blend shape values are coming as 100 scaled **/); } } } } } } GWarn->EndSlowTask(); } // // importing custom attribute START // if (ImportOptions->bImportCustomAttribute) { GWarn->BeginSlowTask( LOCTEXT("BeginImportMorphTargetCurves", "Importing Custom Attirubte Curves"), true); const int32 TotalLinks = SortedLinks.Num(); int32 CurLinkIndex=0; for(auto Node: SortedLinks) { FbxProperty Property = Node->GetFirstProperty(); while (Property.IsValid()) { FbxAnimCurveNode* CurveNode = Property.GetCurveNode(); // do this if user defined and animated and leaf node if( CurveNode && Property.GetFlag(FbxPropertyAttr::eUserDefined) && CurveNode->IsAnimated() && IsSupportedCurveDataType(Property.GetPropertyDataType().GetType()) ) { FString CurveName = UTF8_TO_TCHAR(CurveNode->GetName()); UE_LOG(LogFbx, Log, TEXT("CurveName : %s"), *CurveName ); int32 TotalCount = CurveNode->GetChannelsCount(); for (int32 ChannelIndex=0; ChannelIndex<TotalCount; ++ChannelIndex) { FbxAnimCurve * AnimCurve = CurveNode->GetCurve(ChannelIndex); FString ChannelName = CurveNode->GetChannelName(ChannelIndex).Buffer(); if (AnimCurve) { FString FinalCurveName; if (TotalCount == 1) { FinalCurveName = CurveName; } else { FinalCurveName = CurveName + "_" + ChannelName; } FFormatNamedArguments Args; Args.Add(TEXT("CurveName"), FText::FromString(FinalCurveName)); const FText StatusUpate = FText::Format(LOCTEXT("ImportingCustomAttributeCurvesDetail", "Importing Custom Attribute [{CurveName}]"), Args); GWarn->StatusUpdate(CurLinkIndex + 1, TotalLinks, StatusUpate); ImportCurveToAnimSequence(DestSeq, FinalCurveName, AnimCurve, ACF_DefaultCurve, AnimTimeSpan); } } } Property = Node->GetNextProperty(Property); } CurLinkIndex++; } GWarn->EndSlowTask(); } // importing custom attribute END const bool bSourceDataExists = (DestSeq->SourceRawAnimationData.Num() > 0); TArray<AnimationTransformDebug::FAnimationTransformDebugData> TransformDebugData; int32 TotalNumKeys = 0; const FReferenceSkeleton& RefSkeleton = Skeleton->GetReferenceSkeleton(); // import animation { GWarn->BeginSlowTask( LOCTEXT("BeginImportAnimation", "Importing Animation"), true); TArray<struct FRawAnimSequenceTrack>& RawAnimationData = bSourceDataExists? DestSeq->SourceRawAnimationData : DestSeq->RawAnimationData; DestSeq->TrackToSkeletonMapTable.Empty(); DestSeq->AnimationTrackNames.Empty(); RawAnimationData.Empty(); TArray<FName> FbxRawBoneNames; FillAndVerifyBoneNames(Skeleton, SortedLinks, FbxRawBoneNames, FileName); UnFbx::FFbxImporter* FbxImporter = UnFbx::FFbxImporter::GetInstance(); const bool bPreserveLocalTransform = FbxImporter->GetImportOptions()->bPreserveLocalTransform; // Build additional transform matrix UFbxAnimSequenceImportData* TemplateData = Cast<UFbxAnimSequenceImportData>(DestSeq->AssetImportData); FbxAMatrix FbxAddedMatrix; BuildFbxMatrixForImportTransform(FbxAddedMatrix, TemplateData); FMatrix AddedMatrix = Converter.ConvertMatrix(FbxAddedMatrix); const int32 NumSamplingKeys = FMath::FloorToInt(AnimTimeSpan.GetDuration().GetSecondDouble() * ResampleRate); const FbxTime TimeIncrement = (NumSamplingKeys > 1)? AnimTimeSpan.GetDuration() / (NumSamplingKeys - 1) : AnimTimeSpan.GetDuration(); for(int32 SourceTrackIdx = 0; SourceTrackIdx < FbxRawBoneNames.Num(); ++SourceTrackIdx) { int32 NumKeysForTrack = 0; // see if it's found in Skeleton FName BoneName = FbxRawBoneNames[SourceTrackIdx]; int32 BoneTreeIndex = RefSkeleton.FindBoneIndex(BoneName); // update status FFormatNamedArguments Args; Args.Add(TEXT("TrackName"), FText::FromName(BoneName)); Args.Add(TEXT("TotalKey"), FText::AsNumber(NumSamplingKeys)); Args.Add(TEXT("TrackIndex"), FText::AsNumber(SourceTrackIdx+1)); Args.Add(TEXT("TotalTracks"), FText::AsNumber(FbxRawBoneNames.Num())); const FText StatusUpate = FText::Format(LOCTEXT("ImportingAnimTrackDetail", "Importing Animation Track [{TrackName}] ({TrackIndex}/{TotalTracks}) - TotalKey {TotalKey}"), Args); GWarn->StatusForceUpdate(SourceTrackIdx + 1, FbxRawBoneNames.Num(), StatusUpate); if (BoneTreeIndex!=INDEX_NONE) { bool bSuccess = true; FRawAnimSequenceTrack RawTrack; RawTrack.PosKeys.Empty(); RawTrack.RotKeys.Empty(); RawTrack.ScaleKeys.Empty(); AnimationTransformDebug::FAnimationTransformDebugData NewDebugData; FbxNode* Link = SortedLinks[SourceTrackIdx]; FbxNode * LinkParent = Link->GetParent(); for(FbxTime CurTime = AnimTimeSpan.GetStart(); CurTime <= AnimTimeSpan.GetStop(); CurTime += TimeIncrement) { // save global trasnform FbxAMatrix GlobalMatrix = Link->EvaluateGlobalTransform(CurTime); // we'd like to verify this before going to Transform. // currently transform has tons of NaN check, so it will crash there FMatrix GlobalUEMatrix = Converter.ConvertMatrix(GlobalMatrix); if (GlobalUEMatrix.ContainsNaN()) { bSuccess = false; AddTokenizedErrorMessage(FTokenizedMessage::Create(EMessageSeverity::Error, FText::Format(LOCTEXT("Error_InvalidTransform", "Track {0} contains invalid transform. Could not import the track."), FText::FromName(BoneName))), FFbxErrors::Animation_TransformError); break; } FTransform GlobalTransform = Converter.ConvertTransform(GlobalMatrix); if (GlobalTransform.ContainsNaN()) { bSuccess = false; AddTokenizedErrorMessage(FTokenizedMessage::Create(EMessageSeverity::Error, FText::Format(LOCTEXT("Error_InvalidUnrealTransform", "Track {0} did not yeild valid transform. Please report this to animation team."), FText::FromName(BoneName))), FFbxErrors::Animation_TransformError); break; } // debug data, including import transformation FTransform AddedTransform(AddedMatrix); NewDebugData.SourceGlobalTransform.Add(GlobalTransform * AddedTransform); FTransform LocalTransform; if( !bPreserveLocalTransform && LinkParent) { // I can't rely on LocalMatrix. I need to recalculate quaternion/scale based on global transform if Parent exists FbxAMatrix ParentGlobalMatrix = Link->GetParent()->EvaluateGlobalTransform(CurTime); FTransform ParentGlobalTransform = Converter.ConvertTransform(ParentGlobalMatrix); LocalTransform = GlobalTransform.GetRelativeTransform(ParentGlobalTransform); NewDebugData.SourceParentGlobalTransform.Add(ParentGlobalTransform); } else { FbxAMatrix& LocalMatrix = Link->EvaluateLocalTransform(CurTime); FbxVector4 NewLocalT = LocalMatrix.GetT(); FbxVector4 NewLocalS = LocalMatrix.GetS(); FbxQuaternion NewLocalQ = LocalMatrix.GetQ(); LocalTransform.SetTranslation(Converter.ConvertPos(NewLocalT)); LocalTransform.SetScale3D(Converter.ConvertScale(NewLocalS)); LocalTransform.SetRotation(Converter.ConvertRotToQuat(NewLocalQ)); NewDebugData.SourceParentGlobalTransform.Add(FTransform::Identity); } if(TemplateData && BoneTreeIndex == 0) { // If we found template data earlier, apply the import transform matrix to // the root track. LocalTransform.SetFromMatrix(LocalTransform.ToMatrixWithScale() * AddedMatrix); } if (LocalTransform.ContainsNaN()) { bSuccess = false; AddTokenizedErrorMessage(FTokenizedMessage::Create(EMessageSeverity::Error, FText::Format(LOCTEXT("Error_InvalidUnrealLocalTransform", "Track {0} did not yeild valid local transform. Please report this to animation team."), FText::FromName(BoneName))), FFbxErrors::Animation_TransformError); break; } RawTrack.ScaleKeys.Add(LocalTransform.GetScale3D()); RawTrack.PosKeys.Add(LocalTransform.GetTranslation()); RawTrack.RotKeys.Add(LocalTransform.GetRotation()); NewDebugData.RecalculatedLocalTransform.Add(LocalTransform); ++NumKeysForTrack; } if (bSuccess) { //add new track int32 NewTrackIdx = RawAnimationData.Add(RawTrack); DestSeq->AnimationTrackNames.Add(BoneName); NewDebugData.SetTrackData(NewTrackIdx, BoneTreeIndex, BoneName); // add mapping to skeleton bone track DestSeq->TrackToSkeletonMapTable.Add(FTrackToSkeletonMap(BoneTreeIndex)); TransformDebugData.Add(NewDebugData); } } TotalNumKeys = FMath::Max( TotalNumKeys, NumKeysForTrack ); } DestSeq->NumFrames = TotalNumKeys; GWarn->EndSlowTask(); } // compress animation { GWarn->BeginSlowTask( LOCTEXT("BeginCompressAnimation", "Compress Animation"), true); GWarn->StatusForceUpdate(1, 1, LOCTEXT("CompressAnimation", "Compressing Animation")); // if source data exists, you should bake it to Raw to apply if(bSourceDataExists) { DestSeq->BakeTrackCurvesToRawAnimation(); } else { // otherwise just compress DestSeq->PostProcessSequence(); } // run debug mode AnimationTransformDebug::OutputAnimationTransformDebugData(TransformDebugData, TotalNumKeys, RefSkeleton); GWarn->EndSlowTask(); } return true; }
void Resource::FBX::FBXMaterial::InitMaterial(const FbxSurfaceMaterial *pFbxMaterial, Resource::ResourceManager& rm) { // Logger::Debug(pFbxMaterial->GetName()); Render::MaterialElement& material = AddElement(); const FbxImplementation *lImplementation = pFbxMaterial->GetDefaultImplementation(); FbxPropertyT<FbxDouble3> lKFbxDouble3; FbxPropertyT<FbxDouble> lKFbxDouble1; FbxColor theColor; if(lImplementation){ const FbxBindingTable *lTable = lImplementation->GetRootTable(); size_t lEntryNum = lTable->GetEntryCount(); for (int i = 0; i < (int) lEntryNum; ++i) { const FbxBindingTableEntry &lEntry = lTable->GetEntry(i); const char *lEntrySrcType = lEntry.GetEntryType(true); FbxProperty lFbxProp; FbxString lTest = lEntry.GetSource(); FBXSDK_printf(" Entry: %s\n", lTest.Buffer()); if (strcmp(FbxPropertyEntryView::sEntryType, lEntrySrcType) == 0) { lFbxProp = pFbxMaterial->FindPropertyHierarchical(lEntry.GetSource()); if (!lFbxProp.IsValid()) { lFbxProp = pFbxMaterial->RootProperty.FindHierarchical(lEntry.GetSource()); } } else if (strcmp(FbxConstantEntryView::sEntryType, lEntrySrcType) == 0) { lFbxProp = lImplementation->GetConstants().FindHierarchical(lEntry.GetSource()); } } } else if (pFbxMaterial->GetClassId().Is(FbxSurfacePhong::ClassId)) { // We found a Phong material. Display its properties. // Display the Ambient Color lKFbxDouble3 =((FbxSurfacePhong *) pFbxMaterial)->Ambient; theColor.Set(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2]); // Display the Diffuse Color lKFbxDouble3 =((FbxSurfacePhong *) pFbxMaterial)->Diffuse; theColor.Set(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2]); // Display the Specular Color (unique to Phong materials) lKFbxDouble3 =((FbxSurfacePhong *) pFbxMaterial)->Specular; theColor.Set(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2]); // Display the Emissive Color lKFbxDouble3 =((FbxSurfacePhong *) pFbxMaterial)->Emissive; theColor.Set(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2]); //Opacity is Transparency factor now lKFbxDouble1 =((FbxSurfacePhong *) pFbxMaterial)->TransparencyFactor; // Display the Shininess lKFbxDouble1 =((FbxSurfacePhong *) pFbxMaterial)->Shininess; double dShininess = lKFbxDouble1.Get(); lKFbxDouble1 =((FbxSurfacePhong *) pFbxMaterial)->Specular; double dSpecular = lKFbxDouble1.Get(); lKFbxDouble1 =((FbxSurfacePhong *) pFbxMaterial)->SpecularFactor; double dSpecularFactor = lKFbxDouble1.Get(); material.m_fShininess = dShininess; material.m_fSpecular = dSpecular * dSpecularFactor; // Display the Reflectivity lKFbxDouble1 =((FbxSurfacePhong *) pFbxMaterial)->ReflectionFactor; material.m_fReflectionFactor = lKFbxDouble1.Get(); } else if(pFbxMaterial->GetClassId().Is(FbxSurfaceLambert::ClassId) ) { // We found a Lambert material. Display its properties. // Display the Ambient Color lKFbxDouble3=((FbxSurfaceLambert *)pFbxMaterial)->Ambient; theColor.Set(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2]); // Display the Diffuse Color lKFbxDouble3 =((FbxSurfaceLambert *)pFbxMaterial)->Diffuse; theColor.Set(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2]); // Display the Emissive lKFbxDouble3 =((FbxSurfaceLambert *)pFbxMaterial)->Emissive; theColor.Set(lKFbxDouble3.Get()[0], lKFbxDouble3.Get()[1], lKFbxDouble3.Get()[2]); // Display the Opacity lKFbxDouble1 =((FbxSurfaceLambert *)pFbxMaterial)->TransparencyFactor; } else Logger::Debug("Unknown type of Material"); FbxProperty prop = pFbxMaterial->FindProperty(FbxSurfaceMaterial::sDiffuse); // Check if it's layeredtextures int layeredTextureCount = prop.GetSrcObjectCount<FbxLayeredTexture>(); for (int j = 0; j < layeredTextureCount; j++) { FbxLayeredTexture* layered_texture = FbxCast<FbxLayeredTexture>(prop.GetSrcObject<FbxLayeredTexture>(j)); int lcount = layered_texture->GetSrcObjectCount<FbxFileTexture>(); for (int k = 0; k < lcount; k++) { FbxFileTexture* texture = FbxCast<FbxFileTexture>(layered_texture->GetSrcObject<FbxFileTexture>(k)); // Then, you can get all the properties of the texture, include its name const char* textureName = texture->GetFileName(); material.AddTexture(rm.LoadImageFromFile(textureName)); } } int textureCount = prop.GetSrcObjectCount<FbxFileTexture>(); for(int i=0; i<textureCount; ++i){ FbxFileTexture* texture = FbxCast<FbxFileTexture>(prop.GetSrcObject<FbxFileTexture>(i)); const char* textureName = texture->GetFileName(); material.AddTexture(rm.LoadImageFromFile(textureName)); } FbxPropertyT<FbxString> lString; lString = pFbxMaterial->ShadingModel; }
//=============================================================================================================================== void FBXLoader::LoadMaterialTexture(FbxSurfaceMaterial* inMaterial, ZShadeSandboxLighting::ShaderMaterial*& ioMaterial) { uint32 textureIndex = 0; FbxProperty property; FBXSDK_FOR_EACH_TEXTURE(textureIndex) { property = inMaterial->FindProperty(FbxLayerElement::sTextureChannelNames[textureIndex]); if (property.IsValid()) { uint32 textureCount = property.GetSrcObjectCount<FbxTexture>(); for (uint32 i = 0; i < textureCount; ++i) { FbxLayeredTexture* layeredTexture = property.GetSrcObject<FbxLayeredTexture>(i); if(layeredTexture) { throw std::exception("Layered Texture is currently unsupported\n"); } else { FbxTexture* texture = property.GetSrcObject<FbxTexture>(i); if (texture) { std::string textureType = property.GetNameAsCStr(); FbxFileTexture* fileTexture = FbxCast<FbxFileTexture>(texture); if (fileTexture) { string str_filename(fileTexture->GetFileName()); std::size_t index = str_filename.find_last_of('/\\'); if (index != string::npos) { BetterString str(fileTexture->GetFileName()); int dot_index = str.get_index('.'); BetterString pathName = str.substring(index + 1, dot_index); BetterString ext = str.substring(dot_index + 1); BetterString filename = pathName + "." + ext; str_filename = filename.toString(); } if (textureType == "DiffuseColor") { ioMaterial->sDiffuseTextureName = str_filename; ioMaterial->bHasDiffuseTexture = true; } else if (textureType == "SpecularColor") { ioMaterial->sSpecularTextureName = str_filename; ioMaterial->bHasSpecularTexture = true; } else if (textureType == "Bump") { ioMaterial->sNormalMapTextureName = str_filename; ioMaterial->bHasNormalMapTexture = true; } } } } } } } ioMaterial->SetD3D(m_pD3DSystem); bool addToMM = false; if (ioMaterial->bHasDiffuseTexture) { ZShadeSandboxLighting::ShaderMaterial* material; if (material = MaterialManager::Instance()->GetMaterial(ioMaterial->sMaterialName)) { // The texture has already been loaded ioMaterial->SetMaterialDiffuseTexture(material->DiffuseTexture()); } else { // Need to load new texture ioMaterial->AddDiffuseTexture(m_pGD3D->m_textures_path, ioMaterial->sDiffuseTextureName); addToMM = true; } } if (ioMaterial->bHasSpecularTexture) { ZShadeSandboxLighting::ShaderMaterial* material; if (material = MaterialManager::Instance()->GetMaterial(ioMaterial->sMaterialName)) { // The texture has already been loaded ioMaterial->SetMaterialSpecularTexture(material->SpecularTexture()); } else { // Need to load new texture ioMaterial->AddDiffuseTexture(m_pGD3D->m_textures_path, ioMaterial->sSpecularTextureName); addToMM = true; } } if (ioMaterial->bHasNormalMapTexture) { ZShadeSandboxLighting::ShaderMaterial* material; if (material = MaterialManager::Instance()->GetMaterial(ioMaterial->sMaterialName)) { // The texture has already been loaded ioMaterial->SetMaterialNormalMapTexture(material->NormalMapTexture()); } else { // Need to load new texture ioMaterial->AddDiffuseTexture(m_pGD3D->m_textures_path, ioMaterial->sNormalMapTextureName); addToMM = true; } } if (addToMM) { MaterialManager::Instance()->Add(ioMaterial); } }
StateSetContent FbxMaterialToOsgStateSet::convert(const FbxSurfaceMaterial* pFbxMat) { FbxMaterialMap::const_iterator it = _fbxMaterialMap.find(pFbxMat); if (it != _fbxMaterialMap.end()) return it->second; osg::ref_ptr<osg::Material> pOsgMat = new osg::Material; pOsgMat->setName(pFbxMat->GetName()); StateSetContent result; result.material = pOsgMat; FbxString shadingModel = pFbxMat->ShadingModel.Get(); const FbxSurfaceLambert* pFbxLambert = FbxCast<FbxSurfaceLambert>(pFbxMat); // diffuse map... const FbxProperty lProperty = pFbxMat->FindProperty(FbxSurfaceMaterial::sDiffuse); if (lProperty.IsValid()) { int lNbTex = lProperty.GetSrcObjectCount<FbxFileTexture>(); for (int lTextureIndex = 0; lTextureIndex < lNbTex; lTextureIndex++) { FbxFileTexture* lTexture = FbxCast<FbxFileTexture>(lProperty.GetSrcObject<FbxFileTexture>(lTextureIndex)); if (lTexture) { result.diffuseTexture = fbxTextureToOsgTexture(lTexture); result.diffuseChannel = lTexture->UVSet.Get(); result.diffuseScaleU = lTexture->GetScaleU(); result.diffuseScaleV = lTexture->GetScaleV(); } //For now only allow 1 texture break; } } // opacity map... const FbxProperty lOpacityProperty = pFbxMat->FindProperty(FbxSurfaceMaterial::sTransparentColor); if (lOpacityProperty.IsValid()) { int lNbTex = lOpacityProperty.GetSrcObjectCount<FbxFileTexture>(); for (int lTextureIndex = 0; lTextureIndex < lNbTex; lTextureIndex++) { FbxFileTexture* lTexture = FbxCast<FbxFileTexture>(lOpacityProperty.GetSrcObject<FbxFileTexture>(lTextureIndex)); if (lTexture) { // TODO: if texture image does NOT have an alpha channel, should it be added? result.opacityTexture = fbxTextureToOsgTexture(lTexture); result.opacityChannel = lTexture->UVSet.Get(); result.opacityScaleU = lTexture->GetScaleU(); result.opacityScaleV = lTexture->GetScaleV(); } //For now only allow 1 texture break; } } // reflection map... const FbxProperty lReflectionProperty = pFbxMat->FindProperty(FbxSurfaceMaterial::sReflection); if (lReflectionProperty.IsValid()) { int lNbTex = lReflectionProperty.GetSrcObjectCount<FbxFileTexture>(); for (int lTextureIndex = 0; lTextureIndex < lNbTex; lTextureIndex++) { FbxFileTexture* lTexture = FbxCast<FbxFileTexture>(lReflectionProperty.GetSrcObject<FbxFileTexture>(lTextureIndex)); if (lTexture) { // support only spherical reflection maps... if (FbxFileTexture::eUMT_ENVIRONMENT == lTexture->CurrentMappingType.Get()) { result.reflectionTexture = fbxTextureToOsgTexture(lTexture); result.reflectionChannel = lTexture->UVSet.Get(); } } //For now only allow 1 texture break; } } // emissive map... const FbxProperty lEmissiveProperty = pFbxMat->FindProperty(FbxSurfaceMaterial::sEmissive); if (lEmissiveProperty.IsValid()) { int lNbTex = lEmissiveProperty.GetSrcObjectCount<FbxFileTexture>(); for (int lTextureIndex = 0; lTextureIndex < lNbTex; lTextureIndex++) { FbxFileTexture* lTexture = FbxCast<FbxFileTexture>(lEmissiveProperty.GetSrcObject<FbxFileTexture>(lTextureIndex)); if (lTexture) { result.emissiveTexture = fbxTextureToOsgTexture(lTexture); result.emissiveChannel = lTexture->UVSet.Get(); result.emissiveScaleU = lTexture->GetScaleU(); result.emissiveScaleV = lTexture->GetScaleV(); } //For now only allow 1 texture break; } } if (pFbxLambert) { FbxDouble3 color = pFbxLambert->Diffuse.Get(); double factor = pFbxLambert->DiffuseFactor.Get(); pOsgMat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4( static_cast<float>(color[0] * factor), static_cast<float>(color[1] * factor), static_cast<float>(color[2] * factor), static_cast<float>(1.0 - pFbxLambert->TransparencyFactor.Get()))); color = pFbxLambert->Ambient.Get(); factor = pFbxLambert->AmbientFactor.Get(); pOsgMat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4( static_cast<float>(color[0] * factor), static_cast<float>(color[1] * factor), static_cast<float>(color[2] * factor), 1.0f)); color = pFbxLambert->Emissive.Get(); factor = pFbxLambert->EmissiveFactor.Get(); pOsgMat->setEmission(osg::Material::FRONT_AND_BACK, osg::Vec4( static_cast<float>(color[0] * factor), static_cast<float>(color[1] * factor), static_cast<float>(color[2] * factor), 1.0f)); // get maps factors... result.diffuseFactor = pFbxLambert->DiffuseFactor.Get(); if (const FbxSurfacePhong* pFbxPhong = FbxCast<FbxSurfacePhong>(pFbxLambert)) { color = pFbxPhong->Specular.Get(); factor = pFbxPhong->SpecularFactor.Get(); pOsgMat->setSpecular(osg::Material::FRONT_AND_BACK, osg::Vec4( static_cast<float>(color[0] * factor), static_cast<float>(color[1] * factor), static_cast<float>(color[2] * factor), 1.0f)); pOsgMat->setShininess(osg::Material::FRONT_AND_BACK, static_cast<float>(pFbxPhong->Shininess.Get())); // get maps factors... result.reflectionFactor = pFbxPhong->ReflectionFactor.Get(); // get more factors here... } } if (_lightmapTextures) { // if using an emission map then adjust material properties accordingly... if (result.emissiveTexture) { osg::Vec4 diffuse = pOsgMat->getDiffuse(osg::Material::FRONT_AND_BACK); pOsgMat->setEmission(osg::Material::FRONT_AND_BACK, diffuse); pOsgMat->setDiffuse(osg::Material::FRONT_AND_BACK, osg::Vec4(0,0,0,diffuse.a())); pOsgMat->setAmbient(osg::Material::FRONT_AND_BACK, osg::Vec4(0,0,0,diffuse.a())); } } _fbxMaterialMap.insert(FbxMaterialMap::value_type(pFbxMat, result)); return result; }
FbxDouble3 CFBXLoader::GetMaterialProperty( const FbxSurfaceMaterial * pMaterial, const char * pPropertyName, const char * pFactorPropertyName, FBX_MATRIAL_ELEMENT* pElement) { pElement->type = FBX_MATRIAL_ELEMENT::ELEMENT_NONE; FbxDouble3 lResult(0, 0, 0); const FbxProperty lProperty = pMaterial->FindProperty(pPropertyName); const FbxProperty lFactorProperty = pMaterial->FindProperty(pFactorPropertyName); if (lProperty.IsValid() && lFactorProperty.IsValid()) { lResult = lProperty.Get<FbxDouble3>(); double lFactor = lFactorProperty.Get<FbxDouble>(); if (lFactor != 1) { lResult[0] *= lFactor; lResult[1] *= lFactor; lResult[2] *= lFactor; } pElement->type = FBX_MATRIAL_ELEMENT::ELEMENT_COLOR; } if (lProperty.IsValid()) { int existTextureCount = 0; const int lTextureCount = lProperty.GetSrcObjectCount<FbxFileTexture>(); for(int i=0;i<lTextureCount;i++) { FbxFileTexture* lFileTexture = lProperty.GetSrcObject<FbxFileTexture>(i); if(!lFileTexture) continue; FbxString uvsetName = lFileTexture->UVSet.Get(); std::string uvSetString = uvsetName.Buffer(); std::string filepath = lFileTexture->GetFileName(); pElement->textureSetArray[uvSetString].push_back(filepath); existTextureCount++; } const int lLayeredTextureCount = lProperty.GetSrcObjectCount<FbxLayeredTexture>(); for(int i=0;i<lLayeredTextureCount;i++) { FbxLayeredTexture* lLayeredTexture = lProperty.GetSrcObject<FbxLayeredTexture>(i); const int lTextureFileCount = lLayeredTexture->GetSrcObjectCount<FbxFileTexture>(); for(int j=0;j<lTextureFileCount;j++) { FbxFileTexture* lFileTexture = lLayeredTexture->GetSrcObject<FbxFileTexture>(j); if(!lFileTexture) continue; FbxString uvsetName = lFileTexture->UVSet.Get(); std::string uvSetString = uvsetName.Buffer(); std::string filepath = lFileTexture->GetFileName(); pElement->textureSetArray[uvSetString].push_back(filepath); existTextureCount++; } } if(existTextureCount > 0) { if(pElement->type == FBX_MATRIAL_ELEMENT::ELEMENT_COLOR) pElement->type = FBX_MATRIAL_ELEMENT::ELEMENT_BOTH; else pElement->type = FBX_MATRIAL_ELEMENT::ELEMENT_TEXTURE; } } return lResult; }
//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())); } }
void Tools::DisplayAnimation::DisplayChannels( FbxNode* i_node, FbxAnimLayer* i_animLayer, void (*DisplayCurve) (FbxAnimCurve* i_curve), void (*DisplayListCurve) (FbxAnimCurve* i_curve, FbxProperty* i_property), bool isSwitcher ) { FbxAnimCurve *animCurve = NULL; // Display general curves. if (!isSwitcher) { animCurve = i_node->LclTranslation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_X ); if( animCurve ) { FBXSDK_printf( " TX\n" ); DisplayCommon::DisplayString( " TX" ); DisplayCurve( animCurve ); } animCurve = i_node->LclTranslation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Y ); if( animCurve ) { FBXSDK_printf( " TY\n" ); DisplayCommon::DisplayString( " TY" ); DisplayCurve( animCurve ); } animCurve = i_node->LclTranslation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Z ); if( animCurve ) { FBXSDK_printf( " TZ\n" ); DisplayCommon::DisplayString( " TZ" ); DisplayCurve( animCurve ); } animCurve = i_node->LclRotation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_X ); if( animCurve ) { FBXSDK_printf( " RX\n" ); DisplayCommon::DisplayString( " RX" ); DisplayCurve( animCurve ); } animCurve = i_node->LclRotation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Y ); if( animCurve ) { FBXSDK_printf( " RY\n" ); DisplayCommon::DisplayString( " RY" ); DisplayCurve( animCurve ); } animCurve = i_node->LclRotation.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Z ); if( animCurve ) { FBXSDK_printf( " RZ\n" ); DisplayCommon::DisplayString( " RZ" ); DisplayCurve( animCurve ); } animCurve = i_node->LclScaling.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_X ); if( animCurve ) { FBXSDK_printf( " SX\n" ); DisplayCommon::DisplayString( " SX" ); DisplayCurve( animCurve ); } animCurve = i_node->LclScaling.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Y ); if( animCurve ) { FBXSDK_printf( " SY\n" ); DisplayCommon::DisplayString( " SY" ); DisplayCurve( animCurve ); } animCurve = i_node->LclScaling.GetCurve( i_animLayer, FBXSDK_CURVENODE_COMPONENT_Z ); if( animCurve ) { FBXSDK_printf( " SZ\n" ); DisplayCommon::DisplayString( " SZ" ); DisplayCurve( animCurve ); } } // Display curves specific to a light or marker. FbxNodeAttribute *nodeAttribute = i_node->GetNodeAttribute(); if( nodeAttribute ) { animCurve = nodeAttribute->Color.GetCurve( i_animLayer, FBXSDK_CURVENODE_COLOR_RED ); if( animCurve ) { FBXSDK_printf( " Red\n" ); DisplayCommon::DisplayString( " Red" ); DisplayCurve( animCurve ); } animCurve = nodeAttribute->Color.GetCurve( i_animLayer, FBXSDK_CURVENODE_COLOR_GREEN ); if( animCurve ) { FBXSDK_printf( " Green\n" ); DisplayCommon::DisplayString( " Green" ); DisplayCurve( animCurve ); } animCurve = nodeAttribute->Color.GetCurve( i_animLayer, FBXSDK_CURVENODE_COLOR_BLUE ); if( animCurve ) { FBXSDK_printf( " Blue\n" ); DisplayCommon::DisplayString( " Blue" ); DisplayCurve( animCurve ); } // Display curves specific to a light. FbxLight *light = i_node->GetLight(); if( light ) { animCurve = light->Intensity.GetCurve( i_animLayer ); if( animCurve ) { FBXSDK_printf( " Intensity\n" ); DisplayCommon::DisplayString( " Intensity" ); DisplayCurve( animCurve ); } animCurve = light->OuterAngle.GetCurve( i_animLayer ); if( animCurve ) { FBXSDK_printf( " Outer Angle\n" ); DisplayCommon::DisplayString( " Outer Angle" ); DisplayCurve( animCurve ); } animCurve = light->Fog.GetCurve( i_animLayer ); if( animCurve ) { FBXSDK_printf( " Fog\n" ); DisplayCommon::DisplayString( " Fog" ); DisplayCurve( animCurve ); } } // Display curves specific to a camera. FbxCamera *camera = i_node->GetCamera(); if( camera ) { animCurve = camera->FieldOfView.GetCurve( i_animLayer ); if( animCurve ) { FBXSDK_printf( " Field of View\n" ); DisplayCommon::DisplayString( " Field of View" ); DisplayCurve( animCurve ); } animCurve = camera->FieldOfViewX.GetCurve( i_animLayer ); if( animCurve ) { FBXSDK_printf( " Field of View X\n" ); DisplayCommon::DisplayString( " Field of View X" ); DisplayCurve( animCurve ); } animCurve = camera->FieldOfViewY.GetCurve( i_animLayer ); if( animCurve ) { FBXSDK_printf( " Field of View Y\n" ); DisplayCommon::DisplayString( " Field of View Y" ); DisplayCurve( animCurve ); } animCurve = camera->OpticalCenterX.GetCurve( i_animLayer ); if( animCurve ) { FBXSDK_printf( " Optical Center X\n" ); DisplayCommon::DisplayString( " Optical Center X" ); DisplayCurve( animCurve ); } animCurve = camera->OpticalCenterY.GetCurve( i_animLayer ); if( animCurve ) { FBXSDK_printf( " Optical Center Y\n" ); DisplayCommon::DisplayString( " Optical Center Y" ); DisplayCurve( animCurve ); } animCurve = camera->Roll.GetCurve( i_animLayer ); if( animCurve ) { FBXSDK_printf( " Roll\n" ); DisplayCommon::DisplayString( " Roll" ); DisplayCurve( animCurve ); } } // Display curves specific to a geometry. if (nodeAttribute->GetAttributeType() == FbxNodeAttribute::eMesh || nodeAttribute->GetAttributeType() == FbxNodeAttribute::eNurbs || nodeAttribute->GetAttributeType() == FbxNodeAttribute::ePatch) { FbxGeometry *geometry = (FbxGeometry*) nodeAttribute; int blendShapeDeformerCount = geometry->GetDeformerCount( FbxDeformer::eBlendShape ); for( int blendShapeIndex = 0; blendShapeIndex<blendShapeDeformerCount; blendShapeIndex++ ) { FbxBlendShape *blendShape = (FbxBlendShape*)geometry->GetDeformer( blendShapeIndex, FbxDeformer::eBlendShape ); int blendShapeChannelCount = blendShape->GetBlendShapeChannelCount(); for( int channelIndex = 0; channelIndex<blendShapeChannelCount; channelIndex++ ) { FbxBlendShapeChannel *channel = blendShape->GetBlendShapeChannel( channelIndex ); const char *channelName = channel->GetName(); animCurve = geometry->GetShapeChannel( blendShapeIndex, channelIndex, i_animLayer, true ); if( animCurve ) { FBXSDK_printf( " Shape %s\n", channelName ); DisplayCommon::DisplayString( " Shape ", channelName ); DisplayCurve( animCurve ); } } } } } // Display curves specific to properties FbxProperty lProperty = i_node->GetFirstProperty(); while( lProperty.IsValid() ) { if( lProperty.GetFlag(FbxPropertyAttr::eUserDefined) ) { FbxString lFbxFCurveNodeName = lProperty.GetName(); FbxAnimCurveNode* curveNode = lProperty.GetCurveNode( i_animLayer ); if( !curveNode ) { lProperty = i_node->GetNextProperty( lProperty ); continue; } FbxDataType dataType = lProperty.GetPropertyDataType(); if( dataType.GetType() == eFbxBool || dataType.GetType() == eFbxDouble || dataType.GetType() == eFbxFloat || dataType.GetType() == eFbxInt ) { FbxString message; message = " Property "; message += lProperty.GetName(); if( lProperty.GetLabel().GetLen() > 0 ) { message += " (Label: "; message += lProperty.GetLabel(); message += ")"; }; DisplayCommon::DisplayString( message ); for( int c = 0; c < curveNode->GetCurveCount(0U); c++ ) { animCurve = curveNode->GetCurve( 0U, c ); if( animCurve ) DisplayCurve( animCurve ); } } else if( dataType.GetType() == eFbxDouble3 || dataType.GetType() == eFbxDouble4 || dataType.Is(FbxColor3DT) || dataType.Is(FbxColor4DT) ) { char* componentName1 = (dataType.Is(FbxColor3DT) ||dataType.Is(FbxColor4DT)) ? (char*)FBXSDK_CURVENODE_COLOR_RED : (char*)"X"; char* componentName2 = (dataType.Is(FbxColor3DT) ||dataType.Is(FbxColor4DT)) ? (char*)FBXSDK_CURVENODE_COLOR_GREEN : (char*)"Y"; char* componentName3 = (dataType.Is(FbxColor3DT) ||dataType.Is(FbxColor4DT)) ? (char*)FBXSDK_CURVENODE_COLOR_BLUE : (char*)"Z"; FbxString message; message = " Property "; message += lProperty.GetName(); if( lProperty.GetLabel().GetLen() > 0 ) { message += " (Label: "; message += lProperty.GetLabel(); message += ")"; } DisplayCommon::DisplayString( message ); for( int c = 0; c < curveNode->GetCurveCount(0U); c++ ) { animCurve = curveNode->GetCurve( 0U, c ); if( animCurve ) { DisplayCommon::DisplayString( " Component ", componentName1 ); DisplayCurve( animCurve ); } } for( int c = 0; c < curveNode->GetCurveCount(1U); c++ ) { animCurve = curveNode->GetCurve(1U, c); if( animCurve ) { DisplayCommon::DisplayString( " Component ", componentName2 ); DisplayCurve( animCurve ); } } for( int c = 0; c < curveNode->GetCurveCount(2U); c++ ) { animCurve = curveNode->GetCurve( 2U, c ); if( animCurve ) { DisplayCommon::DisplayString( " Component ", componentName3 ); DisplayCurve( animCurve ); } } } else if( dataType.GetType() == eFbxEnum ) { FbxString message; message = " Property "; message += lProperty.GetName(); if( lProperty.GetLabel().GetLen() > 0 ) { message += " (Label: "; message += lProperty.GetLabel(); message += ")"; }; DisplayCommon::DisplayString( message ); for( int c = 0; c < curveNode->GetCurveCount(0U); c++ ) { animCurve = curveNode->GetCurve( 0U, c ); if( animCurve ) DisplayListCurve( animCurve, &lProperty ); } } } lProperty = i_node->GetNextProperty( lProperty ); } // while }
//-------------------------------------------------------------------------------------- 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); } }
// マテリアルプロパティ獲得 FbxDouble3 GetMaterialProperty( const FbxSurfaceMaterial * pMaterial, const char * pPropertyName, const char * pFactorPropertyName) { FbxDouble3 lResult(0, 0, 0); const FbxProperty lProperty = pMaterial->FindProperty(pPropertyName); const FbxProperty lFactorProperty = pMaterial->FindProperty(pFactorPropertyName); if(lProperty.IsValid() && lFactorProperty.IsValid()) { lResult = lProperty.Get<FbxDouble3>(); double lFactor = lFactorProperty.Get<FbxDouble>(); if(lFactor != 1) { lResult[0] *= lFactor; lResult[1] *= lFactor; lResult[2] *= lFactor; } } if(lProperty.IsValid()) { printf("テクスチャ\n"); const int lTextureCount = lProperty.GetSrcObjectCount<FbxFileTexture>(); for(int i = 0; i<lTextureCount; i++) { FbxFileTexture* lFileTexture = lProperty.GetSrcObject<FbxFileTexture>(i); if(lFileTexture) { FbxString uvsetName = lFileTexture->UVSet.Get(); std::string uvSetString = uvsetName.Buffer(); std::string filepath = lFileTexture->GetFileName(); printf("UVSet名=%s\n", uvSetString.c_str()); printf("テクスチャ名=%s\n", filepath.c_str()); } } puts(""); printf("レイヤードテクスチャ\n"); const int lLayeredTextureCount = lProperty.GetSrcObjectCount<FbxLayeredTexture>(); for(int i = 0; i<lLayeredTextureCount; i++) { FbxLayeredTexture* lLayeredTexture = lProperty.GetSrcObject<FbxLayeredTexture>(i); const int lTextureFileCount = lLayeredTexture->GetSrcObjectCount<FbxFileTexture>(); for(int j = 0; j<lTextureFileCount; j++) { FbxFileTexture* lFileTexture = lLayeredTexture->GetSrcObject<FbxFileTexture>(j); if(lFileTexture) { FbxString uvsetName = lFileTexture->UVSet.Get(); std::string uvSetString = uvsetName.Buffer(); std::string filepath = lFileTexture->GetFileName(); printf("UVSet名=%s\n", uvSetString.c_str()); printf("テクスチャ名=%s\n", filepath.c_str()); } } } puts(""); } return lResult; }
//------------------------------------------------------------------------- // //------------------------------------------------------------------------- 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 FbxToHkxConverter::extractKeyFramesAndAnnotations(hkxScene *scene, FbxNode* fbxChildNode, hkxNode* newChildNode, int animStackIndex) { FbxAMatrix bindPoseMatrix; FbxAnimStack* lAnimStack = NULL; int numAnimLayers = 0; FbxTimeSpan animTimeSpan; if (animStackIndex >= 0) { lAnimStack = m_curFbxScene->GetSrcObject<FbxAnimStack>(animStackIndex); numAnimLayers = lAnimStack->GetMemberCount<FbxAnimLayer>(); animTimeSpan = lAnimStack->GetLocalTimeSpan(); } // Find the time offset (in the "time space" of the FBX file) of the first animation frame FbxTime timePerFrame; timePerFrame.SetTime(0, 0, 0, 1, 0, m_curFbxScene->GetGlobalSettings().GetTimeMode()); const FbxTime startTime = animTimeSpan.GetStart(); const FbxTime endTime = animTimeSpan.GetStop(); const hkReal startTimeSeconds = static_cast<hkReal>(startTime.GetSecondDouble()); const hkReal endTimeSeconds = static_cast<hkReal>(endTime.GetSecondDouble()); int numFrames = 0; bool staticNode = true; if (scene->m_sceneLength == 0) { bindPoseMatrix = fbxChildNode->EvaluateLocalTransform(startTime); } else { hkArray<hkStringOld> annotationStrings; hkArray<hkReal> annotationTimes; HK_ASSERT(0x0, newChildNode->m_keyFrames.getSize() == 0); // Sample each animation frame for (FbxTime time = startTime, priorSampleTime = endTime; time < endTime; priorSampleTime = time, time += timePerFrame, ++numFrames) { FbxAMatrix frameMatrix = fbxChildNode->EvaluateLocalTransform(time); staticNode = staticNode && (frameMatrix == bindPoseMatrix); hkMatrix4 mat; // Extract this frame's transform convertFbxXMatrixToMatrix4(frameMatrix, mat); newChildNode->m_keyFrames.pushBack(mat); // Extract all annotation strings for this frame using the deprecated // pipeline (new annotations are extracted when sampling attributes) if (m_options.m_exportAnnotations && numAnimLayers > 0) { FbxProperty prop = fbxChildNode->GetFirstProperty(); while(prop.IsValid()) { FbxString propName = prop.GetName(); FbxDataType lDataType = prop.GetPropertyDataType(); hkStringOld name(propName.Buffer(), (int) propName.GetLen()); if (name.asUpperCase().beginsWith("HK") && lDataType.GetType() == eFbxEnum) { FbxAnimLayer* lAnimLayer = lAnimStack->GetMember<FbxAnimLayer>(0); FbxAnimCurve* lAnimCurve = prop.GetCurve(lAnimLayer); int currentKeyIndex; const int keyIndex = (int) lAnimCurve->KeyFind(time, ¤tKeyIndex); const int priorKeyIndex = (int) lAnimCurve->KeyFind(priorSampleTime); // Only store annotations on frames where they're explicitly keyframed, or if this is the first keyframe if (priorKeyIndex != keyIndex) { const int currentEnumValueIndex = keyIndex < 0 ? (int) lAnimCurve->Evaluate(priorSampleTime) : (int) lAnimCurve->Evaluate(time); HK_ASSERT(0x0, currentEnumValueIndex < prop.GetEnumCount()); const char* enumValue = prop.GetEnumValue(currentEnumValueIndex); hkxNode::AnnotationData& annotation = newChildNode->m_annotations.expandOne(); annotation.m_time = (hkReal) (time - startTime).GetSecondDouble(); annotation.m_description = (name + hkStringOld(enumValue, hkString::strLen(enumValue))).cString(); } } prop = fbxChildNode->GetNextProperty(prop); } } } } // Replace animation key data for static nodes with just 1 or 2 frames of bind pose data if (staticNode) { // Static nodes in animated scene data are exported with two keys const bool exportTwoFramesForStaticNodes = (numFrames > 1); // replace transform newChildNode->m_keyFrames.setSize(exportTwoFramesForStaticNodes ? 2: 1); newChildNode->m_keyFrames.optimizeCapacity(0, true); // convert the bind pose transform to Havok format convertFbxXMatrixToMatrix4(bindPoseMatrix, newChildNode->m_keyFrames[0]); if (exportTwoFramesForStaticNodes) { newChildNode->m_keyFrames[1] = newChildNode->m_keyFrames[0]; } } // Extract all times of actual keyframes for the current node... this can be used by Vision if ( m_options.m_storeKeyframeSamplePoints && newChildNode->m_keyFrames.getSize() > 2 && numAnimLayers > 0 ) { FbxAnimLayer* lAnimLayer = lAnimStack->GetMember<FbxAnimLayer>(0); extractKeyTimes(fbxChildNode, lAnimLayer, FBXSDK_CURVENODE_TRANSLATION, newChildNode, startTimeSeconds, endTimeSeconds); extractKeyTimes(fbxChildNode, lAnimLayer, FBXSDK_CURVENODE_ROTATION, newChildNode, startTimeSeconds, endTimeSeconds); extractKeyTimes(fbxChildNode, lAnimLayer, FBXSDK_CURVENODE_SCALING, newChildNode, startTimeSeconds, endTimeSeconds); extractKeyTimes(fbxChildNode, lAnimLayer, FBXSDK_CURVENODE_COMPONENT_X, newChildNode, startTimeSeconds, endTimeSeconds); extractKeyTimes(fbxChildNode, lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Y, newChildNode, startTimeSeconds, endTimeSeconds); extractKeyTimes(fbxChildNode, lAnimLayer, FBXSDK_CURVENODE_COMPONENT_Z, newChildNode, startTimeSeconds, endTimeSeconds); if (newChildNode->m_linearKeyFrameHints.getSize() > 1) { hkSort(newChildNode->m_linearKeyFrameHints.begin(), newChildNode->m_linearKeyFrameHints.getSize()); } } }