FBXModel::MaterialCollection FBXModel::getMaterials(const GraphicsDevice& device, KFbxNode* node) { MaterialCollection materials; for (int i = 0; i < node->GetMaterialCount(); ++i) { FBXMaterial material; KFbxSurfaceMaterial* surfaceMaterial = node->GetMaterial(i); KFbxProperty prop = surfaceMaterial->FindProperty(KFbxSurfaceMaterial::sDiffuse); if (prop.IsValid()) { int textureCount = prop.GetSrcObjectCount(KFbxFileTexture::ClassId); if (textureCount) { KFbxFileTexture* fbxTexture = prop.GetSrcObject(FBX_TYPE(KFbxFileTexture), 0); if (fbxTexture) material.texture = Texture::createFromFile(device, fbxTexture->GetFileName()); } } if (!material.texture) material.texture = defaultTexture; if (surfaceMaterial->GetClassId().Is(KFbxSurfacePhong::ClassId)) { Material& mat = material.material; KFbxSurfacePhong* phong = (KFbxSurfacePhong*)surfaceMaterial; mat.Ambient = convert(phong->Diffuse.Get()); mat.Diffuse = mat.Ambient; mat.Specular = convert(phong->Specular.Get()); mat.Emissive = convert(phong->Emissive.Get()); mat.Power = (float)phong->SpecularFactor.Get(); } materials.push_back(material); } return materials; }
void ShadingManager::SetMaterial(const KFbxNode * pNode, int pMaterialIndex) const { const KFbxSurfaceMaterial * lSurfaceMaterial = pNode->GetMaterial(pMaterialIndex); if (!lSurfaceMaterial) return; if (lSurfaceMaterial == mLastMaterial) return; mLastMaterial = lSurfaceMaterial; SetMaterialProperty(lSurfaceMaterial, KFbxSurfaceMaterial::sEmissive, KFbxSurfaceMaterial::sEmissiveFactor, GL_EMISSION); SetMaterialProperty(lSurfaceMaterial, KFbxSurfaceMaterial::sAmbient, KFbxSurfaceMaterial::sAmbientFactor, GL_AMBIENT); const TextureObjectsForMaterialType::RecordType * lRecord = mTextureObjectsForMaterial.Find(lSurfaceMaterial); if (lRecord) { glBindTexture(GL_TEXTURE_2D, lRecord->GetValue()); mLastTextureObject = lRecord->GetValue(); } else { mLastTextureObject = 0; } if (!mLastTextureObject) { SetMaterialProperty(lSurfaceMaterial, KFbxSurfaceMaterial::sDiffuse, KFbxSurfaceMaterial::sDiffuseFactor, GL_DIFFUSE); } SetMaterialProperty(lSurfaceMaterial, KFbxSurfaceMaterial::sSpecular, KFbxSurfaceMaterial::sSpecularFactor, GL_SPECULAR); KFbxProperty lShininessProperty = lSurfaceMaterial->FindProperty(KFbxSurfaceMaterial::sShininess); if (lShininessProperty.IsValid()) { double lShininess = 0; lShininess = lShininessProperty.Get(&lShininess); glMaterialf(GL_FRONT, GL_SHININESS, (GLfloat)lShininess); } }
void ShadingManager::Initialize(const KFbxNode* pNode) { if (!pNode) return; if (pNode->GetNodeAttribute()) { const int lMaterialCount = pNode->GetMaterialCount(); for (int lMaterialIndex = 0; lMaterialIndex < lMaterialCount; ++lMaterialIndex) { const KFbxSurfaceMaterial * lMaterial = pNode->GetMaterial(lMaterialIndex); if (lMaterial) { const KFbxProperty lProperty = lMaterial->FindProperty(KFbxSurfaceMaterial::sDiffuse); if (lProperty.IsValid()) { const int lTextureCount = lProperty.GetSrcObjectCount(KFbxFileTexture::ClassId); if (lTextureCount) { const KFbxFileTexture* lTexture = lProperty.GetSrcObject(FBX_TYPE(KFbxFileTexture), 0); if (lTexture) { unsigned int lTextureObject; mTextureManager->LoadTexture(lTexture, &lTextureObject); mTextureObjectsForMaterial.Insert(lMaterial, lTextureObject); } } } } } } const int lChildCount = pNode->GetChildCount(); for (int lChildIndex = 0; lChildIndex < lChildCount; ++lChildIndex) { Initialize(pNode->GetChild(lChildIndex)); } }
bool FBXLoader::DisplayTextureNames( KFbxProperty &pProperty, KString& pConnectionString) { int lLayeredTextureCount = pProperty.GetSrcObjectCount(KFbxLayeredTexture::ClassId); if (lLayeredTextureCount > 0) { for (int j=0; j<lLayeredTextureCount; ++j) { KFbxLayeredTexture *lLayeredTexture = KFbxCast <KFbxLayeredTexture>(pProperty.GetSrcObject(KFbxLayeredTexture::ClassId, j)); int lNbTextures = lLayeredTexture->GetSrcObjectCount(KFbxTexture::ClassId); pConnectionString += " Texture "; for (int k =0; k<lNbTextures; ++k) { pConnectionString += "\""; pConnectionString += (char*)lLayeredTexture->GetName(); pConnectionString += "\""; pConnectionString += " "; } pConnectionString += "of "; pConnectionString += pProperty.GetName(); pConnectionString += " on layer "; pConnectionString += j; } pConnectionString += " |"; return true; } else { int lNbTextures = pProperty.GetSrcObjectCount(KFbxTexture::ClassId); if (lNbTextures > 0) { pConnectionString += " Texture "; pConnectionString += " "; for (int j =0; j<lNbTextures; ++j) { KFbxTexture* lTexture = KFbxCast <KFbxTexture> (pProperty.GetSrcObject(KFbxTexture::ClassId,j)); if (lTexture) { pConnectionString += "\""; pConnectionString += (char*)lTexture->GetName(); pConnectionString += "\""; pConnectionString += " "; } } pConnectionString += "of "; pConnectionString += pProperty.GetName(); pConnectionString += " |"; return true; } return false; } }
void ShadingManager::SetMaterialProperty(const KFbxSurfaceMaterial * pMaterial, const char * pPropertyName, const char * pFactorPropertyName, unsigned int pOGLProperty) const { const KFbxProperty lProperty = pMaterial->FindProperty(pPropertyName); const KFbxProperty lFactorProperty = pMaterial->FindProperty(pFactorPropertyName); if (lProperty.IsValid() && lFactorProperty.IsValid()) { fbxDouble3 lColor = fbxDouble3(0, 0, 0); lColor = lProperty.Get(&lColor); double lFactor = 1; lFactor = lFactorProperty.Get(&lFactor); if (lFactor != 1) { lColor[0] *= lFactor; lColor[1] *= lFactor; lColor[2] *= lFactor; } const GLfloat lMaterial[] = {(GLfloat)lColor[0], (GLfloat)lColor[1], (GLfloat)lColor[2], 1.0f}; glMaterialfv(GL_FRONT, pOGLProperty, lMaterial); } }
bool FBXLoader::FindTextureInfo(KFbxProperty prop, bool& disp, int mat_i, Object* o) { if (prop.IsValid()) { Texture* t; t = new (std::nothrow) Texture; if (t == NULL) { std::cout << "[FbxLoader]{__FindTextureInfo} Error: Can not allocate memory\n"; return (false); } int t_count; int i; t_count = prop.GetSrcObjectCount(KFbxTexture::ClassId); i = 0; while (i < t_count) { KFbxLayeredTexture* lay_t; lay_t = KFbxCast <KFbxLayeredTexture>(prop.GetSrcObject(KFbxLayeredTexture::ClassId, i)); if (lay_t) { KFbxLayeredTexture* lay_t2; int nb_text; int j; lay_t2 = KFbxCast <KFbxLayeredTexture>(prop.GetSrcObject(KFbxLayeredTexture::ClassId, i)); nb_text = lay_t2->GetSrcObjectCount(KFbxTexture::ClassId); j = 0; while (j < nb_text) { KFbxTexture* _t; _t = KFbxCast <KFbxTexture> (lay_t2->GetSrcObject(KFbxTexture::ClassId, j)); if (_t) { KFbxLayeredTexture::EBlendMode blend_mode; if (disp) disp = false; lay_t2->GetTextureBlendMode(j, blend_mode); this->TextureInfoFinded(_t, (int)blend_mode, t); o->GetMatList()->at(mat_i)->AddTexture(t); } ++j; } } else { KFbxTexture* _t; _t = KFbxCast <KFbxTexture> (prop.GetSrcObject(KFbxTexture::ClassId, i)); if (_t) { if (disp) disp = false; if (strcmp(prop.GetName(), "DiffuseColor") == 0) t->SetTXTChanel(0); else if (strcmp(prop.GetName(), "SpecularColor") == 0) t->SetTXTChanel(3); this->TextureInfoFinded(_t, -1, t); o->GetMatList()->at(mat_i)->AddTexture(t); } } ++i; } } return (true); }
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; }
void FBXJSONSerializer::recurse_over_model(fbxsdk_2012_1::KFbxNode *fbx_node, json::Array& meshes_array) { KFbxMesh* old_mesh = fbx_node->GetMesh(); if (old_mesh) { KFbxGeometryConverter converter(fbx_node->GetFbxSdkManager()); KFbxMesh* mesh = converter.TriangulateMesh(old_mesh); mesh->ComputeBBox(); mesh->ComputeVertexNormals(); Object json_mesh; { KFbxLayerElementUV* uvs = mesh->GetLayer(0)->GetUVs(); KFbxLayerElementNormal* normals = mesh->GetLayer(0, KFbxLayerElement::eNORMAL)->GetNormals(); Array json_mesh_normals; Array json_mesh_uvs; Array json_mesh_vertices; int polygon_count = mesh->GetPolygonCount(); for (int poly_index = 0; poly_index < polygon_count; poly_index++) { for (int vertex_index = 0; vertex_index < mesh->GetPolygonSize(poly_index); vertex_index++) { int vertex_position = mesh->GetPolygonVertex(poly_index, vertex_index); KFbxVector4 vertex = mesh->GetControlPoints()[vertex_position]; Number vertex_x = vertex.GetAt(0); json_mesh_vertices.Insert(vertex_x); Number vertex_y = vertex.GetAt(1); json_mesh_vertices.Insert(vertex_y); Number vertex_z = vertex.GetAt(2); json_mesh_vertices.Insert(vertex_z); KFbxVector4 normal = normals->GetDirectArray()[vertex_position]; Number normal_x = normal.GetAt(0); json_mesh_normals.Insert(normal_x); Number normal_y = normal.GetAt(1); json_mesh_normals.Insert(normal_y); Number normal_z = normal.GetAt(2); json_mesh_normals.Insert(normal_z); if (uvs) { int mesh_index = mesh->GetTextureUVIndex(poly_index, vertex_index); KFbxVector2 uv = uvs->GetDirectArray().GetAt(mesh_index); Number uv_x = 1.0f-uv[0]; json_mesh_uvs.Insert(uv_x); // these are flipped Number uv_y = 1.0f-uv[1]; json_mesh_uvs.Insert(uv_y); } } } json_mesh["vertices"] = json_mesh_vertices; json_mesh["normals"] = json_mesh_normals; json_mesh["uvs"] = json_mesh_uvs; } { fbxDouble3 scale = fbx_node->LclScaling.Get(); Object json_mesh_scale; json_mesh_scale["x"] = Number(scale[0]); json_mesh_scale["y"] = Number(scale[1]); json_mesh_scale["z"] = Number(scale[2]); json_mesh["scale"] = json_mesh_scale; } { fbxDouble3 translation = fbx_node->LclTranslation.Get(); Object json_mesh_translation; json_mesh_translation["x"] = Number(translation[0]); json_mesh_translation["y"] = Number(translation[1]); json_mesh_translation["z"] = Number(translation[2]); json_mesh["translation"] = json_mesh_translation; } { fbxDouble3 rotation = fbx_node->LclRotation.Get(); Object json_mesh_rotation; json_mesh_rotation["x"] = Number(rotation[0]); json_mesh_rotation["y"] = Number(rotation[1]); json_mesh_rotation["z"] = Number(rotation[2]); json_mesh["rotation"] = json_mesh_rotation; } { int material_count = fbx_node->GetMaterialCount(); Array json_mesh_materials; for (int material_index = 0; material_index < material_count; material_index++) { KFbxSurfaceMaterial* surface_material = fbx_node->GetMaterial(material_index); Object json_material; Array json_textures; int textureIndex = 0; FOR_EACH_TEXTURE(textureIndex) { KFbxProperty property = surface_material->FindProperty(KFbxLayerElement::TEXTURE_CHANNEL_NAMES[textureIndex]); int layered_texture_count = property.GetSrcObjectCount(KFbxTexture::ClassId); for (int layered_texture_index = 0; layered_texture_index < layered_texture_count; ++layered_texture_index) { KFbxTexture* texture = KFbxCast <KFbxTexture> (property.GetSrcObject(KFbxTexture::ClassId, layered_texture_index)); if(texture) { KFbxFileTexture *file_texture = KFbxCast<KFbxFileTexture>(texture); if (file_texture) { Object json_texture; json_texture["filename"] = String(file_texture->GetFileName()); json_textures.Insert(json_texture); } } } } json_material["textures"] = json_textures; KFbxSurfaceLambert* lambert_material = KFbxCast<KFbxSurfaceLambert>(surface_material); if (lambert_material) { Object diffuse; double diffuse_r = lambert_material->Diffuse.Get()[0]; diffuse["r"] = Number(diffuse_r); double diffuse_g = lambert_material->Diffuse.Get()[1]; diffuse["g"] = Number(diffuse_g); double diffuse_b = lambert_material->Diffuse.Get()[2]; diffuse["b"] = Number(diffuse_b); json_material["diffuse"] = diffuse; Object ambient; double ambient_r = lambert_material->Ambient.Get()[0]; ambient["r"] = Number(ambient_r); double ambient_g = lambert_material->Ambient.Get()[1]; ambient["g"] = Number(ambient_g); double ambient_b = lambert_material->Ambient.Get()[2]; ambient["b"] = Number(ambient_b); json_material["ambient"] = ambient; KFbxProperty specular_property = lambert_material->FindProperty("SpecularColor"); fbxDouble3 specular_data; specular_property.Get(&specular_data, eDOUBLE3); Object specular; float specular_r = specular_data[0]; specular["r"] = Number(specular_r); float specular_g = specular_data[1]; specular["g"] = Number(specular_g); float specular_b = specular_data[2]; specular["b"] = Number(specular_b); json_material["specular"] = specular; } json_mesh_materials.Insert(json_material); } json_mesh["materials"] = json_mesh_materials; } json_mesh["uv_stride"] = Number(2); json_mesh["vertex_stride"] = Number(3); json_mesh["normal_stride"] = Number(3); meshes_array.Insert(json_mesh); } for(int j = 0; j < fbx_node->GetChildCount(); j++) { recurse_over_model(fbx_node->GetChild(j), meshes_array); } }