TextureDetails* FbxMaterialToOsgStateSet::selectTextureDetails(const FbxProperty& lProperty) { if (lProperty.IsValid()) { FbxFileTexture* fileTexture = selectFbxFileTexture(lProperty); if (fileTexture) { TextureDetails* textureDetails = new TextureDetails(); textureDetails->texture = fbxTextureToOsgTexture(fileTexture); textureDetails->channel = fileTexture->UVSet.Get(); textureDetails->scale.set(fileTexture->GetScaleU(), fileTexture->GetScaleV()); return textureDetails; } } return 0; }
StateSetContent FbxMaterialToOsgStateSet::convert(const KFbxSurfaceMaterial* 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 KFbxSurfaceLambert* pFbxLambert = KFbxCast<KFbxSurfaceLambert>(pFbxMat); // diffuse map... const KFbxProperty lProperty = pFbxMat->FindProperty(KFbxSurfaceMaterial::sDiffuse); if (lProperty.IsValid()) { int lNbTex = lProperty.GetSrcObjectCount(KFbxFileTexture::ClassId); for (int lTextureIndex = 0; lTextureIndex < lNbTex; lTextureIndex++) { KFbxFileTexture* lTexture = KFbxCast<KFbxFileTexture>(lProperty.GetSrcObject(KFbxFileTexture::ClassId, 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 KFbxProperty lOpacityProperty = pFbxMat->FindProperty(KFbxSurfaceMaterial::sTransparentColor); if (lOpacityProperty.IsValid()) { int lNbTex = lOpacityProperty.GetSrcObjectCount(KFbxFileTexture::ClassId); for (int lTextureIndex = 0; lTextureIndex < lNbTex; lTextureIndex++) { KFbxFileTexture* lTexture = KFbxCast<KFbxFileTexture>(lOpacityProperty.GetSrcObject(KFbxFileTexture::ClassId, 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 KFbxProperty lReflectionProperty = pFbxMat->FindProperty(KFbxSurfaceMaterial::sReflection); if (lReflectionProperty.IsValid()) { int lNbTex = lReflectionProperty.GetSrcObjectCount(KFbxFileTexture::ClassId); for (int lTextureIndex = 0; lTextureIndex < lNbTex; lTextureIndex++) { KFbxFileTexture* lTexture = KFbxCast<KFbxFileTexture>(lReflectionProperty.GetSrcObject(KFbxFileTexture::ClassId, lTextureIndex)); if (lTexture) { // support only spherical reflection maps... if (KFbxFileTexture::eUMT_ENVIRONMENT == lTexture->CurrentMappingType.Get()) { result.reflectionTexture = fbxTextureToOsgTexture(lTexture); result.reflectionChannel = lTexture->UVSet.Get(); } } //For now only allow 1 texture break; } } // emissive map... const KFbxProperty lEmissiveProperty = pFbxMat->FindProperty(KFbxSurfaceMaterial::sEmissive); if (lEmissiveProperty.IsValid()) { int lNbTex = lEmissiveProperty.GetSrcObjectCount(KFbxFileTexture::ClassId); for (int lTextureIndex = 0; lTextureIndex < lNbTex; lTextureIndex++) { KFbxFileTexture* lTexture = KFbxCast<KFbxFileTexture>(lEmissiveProperty.GetSrcObject(KFbxFileTexture::ClassId, 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 KFbxSurfacePhong* pFbxPhong = KFbxCast<KFbxSurfacePhong>(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; }
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; }