Explorar el Código

Merge pull request #2304 from merwaaan/fbx-keep-material-params

Preserve all the material parameters from FBX models
Kim Kulling hace 6 años
padre
commit
9765eb988a
Se han modificado 2 ficheros con 176 adiciones y 0 borrados
  1. 175 0
      code/FBXConverter.cpp
  2. 1 0
      code/FBXConverter.h

+ 175 - 0
code/FBXConverter.cpp

@@ -1575,6 +1575,7 @@ namespace Assimp {
 
             // shading stuff and colors
             SetShadingPropertiesCommon(out_mat, props);
+            SetShadingPropertiesRaw( out_mat, props, material.Textures(), mesh );
 
             // texture assignments
             SetTextureProperties(out_mat, material.Textures(), mesh);
@@ -2073,6 +2074,180 @@ namespace Assimp {
             const float DispFactor = PropertyGet<float>(props, "DisplacementFactor", ok);
             if (ok) {
                 out_mat->AddProperty(&DispFactor, 1, "$mat.displacementscaling", 0, 0);
+    }
+}
+
+
+void FBXConverter::SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTable& props, const TextureMap& textures, const MeshGeometry* const mesh)
+{
+    // Add all the unparsed properties with a "$raw." prefix
+
+    const std::string prefix = "$raw.";
+
+    for (const DirectPropertyMap::value_type& prop : props.GetUnparsedProperties()) {
+
+        std::string name = prefix + prop.first;
+
+        if (const TypedProperty<aiVector3D>* interpreted = prop.second->As<TypedProperty<aiVector3D> >())
+        {
+            out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0);
+        }
+        else if (const TypedProperty<aiColor3D>* interpreted = prop.second->As<TypedProperty<aiColor3D> >())
+        {
+            out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0);
+        }
+        else if (const TypedProperty<aiColor4D>* interpreted = prop.second->As<TypedProperty<aiColor4D> >())
+        {
+            out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0);
+        }
+        else if (const TypedProperty<float>* interpreted = prop.second->As<TypedProperty<float> >())
+        {
+            out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0);
+        }
+        else if (const TypedProperty<int>* interpreted = prop.second->As<TypedProperty<int> >())
+        {
+            out_mat->AddProperty(&interpreted->Value(), 1, name.c_str(), 0, 0);
+        }
+        else if (const TypedProperty<bool>* interpreted = prop.second->As<TypedProperty<bool> >())
+        {
+            int value = interpreted->Value() ? 1 : 0;
+            out_mat->AddProperty(&value, 1, name.c_str(), 0, 0);
+        }
+        else if (const TypedProperty<std::string>* interpreted = prop.second->As<TypedProperty<std::string> >())
+        {
+            const aiString value = aiString(interpreted->Value());
+            out_mat->AddProperty(&value, name.c_str(), 0, 0);
+        }
+    }
+
+    // Add the textures' properties
+
+    for (TextureMap::const_iterator it = textures.begin(); it != textures.end(); it++) {
+
+        std::string name = prefix + it->first;
+
+        const Texture* const tex = (*it).second;
+        if (tex != nullptr)
+        {
+            aiString path;
+            path.Set(tex->RelativeFilename());
+
+            const Video* media = tex->Media();
+            if (media != nullptr && media->ContentLength() > 0) {
+                unsigned int index;
+
+                VideoMap::const_iterator it = textures_converted.find(media);
+                if (it != textures_converted.end()) {
+                    index = (*it).second;
+                }
+                else {
+                    index = ConvertVideo(*media);
+                    textures_converted[media] = index;
+                }
+
+                // setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
+                path.data[0] = '*';
+                path.length = 1 + ASSIMP_itoa10(path.data + 1, MAXLEN - 1, index);
+            }
+
+            out_mat->AddProperty(&path, (name + "|file").c_str(), aiTextureType_UNKNOWN, 0);
+
+            aiUVTransform uvTrafo;
+            // XXX handle all kinds of UV transformations
+            uvTrafo.mScaling = tex->UVScaling();
+            uvTrafo.mTranslation = tex->UVTranslation();
+            out_mat->AddProperty(&uvTrafo, 1, (name + "|uvtrafo").c_str(), aiTextureType_UNKNOWN, 0);
+ 
+            int uvIndex = 0;
+
+            bool uvFound = false;
+            const std::string& uvSet = PropertyGet<std::string>(tex->Props(), "UVSet", uvFound);
+            if (uvFound) {
+                // "default" is the name which usually appears in the FbxFileTexture template
+                if (uvSet != "default" && uvSet.length()) {
+                    // this is a bit awkward - we need to find a mesh that uses this
+                    // material and scan its UV channels for the given UV name because
+                    // assimp references UV channels by index, not by name.
+
+                    // XXX: the case that UV channels may appear in different orders
+                    // in meshes is unhandled. A possible solution would be to sort
+                    // the UV channels alphabetically, but this would have the side
+                    // effect that the primary (first) UV channel would sometimes
+                    // be moved, causing trouble when users read only the first
+                    // UV channel and ignore UV channel assignments altogether.
+
+                    std::vector<aiMaterial*>::iterator materialIt = std::find(materials.begin(), materials.end(), out_mat);
+                    const unsigned int matIndex = static_cast<unsigned int>(std::distance(materials.begin(), materialIt));
+
+                    uvIndex = -1;
+                    if (!mesh)
+                    {
+                        for (const MeshMap::value_type& v : meshes_converted) {
+                            const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*>(v.first);
+                            if (!mesh) {
+                                continue;
+                            }
+
+                            const MatIndexArray& mats = mesh->GetMaterialIndices();
+                            if (std::find(mats.begin(), mats.end(), matIndex) == mats.end()) {
+                                continue;
+                            }
+
+                            int index = -1;
+                            for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+                                if (mesh->GetTextureCoords(i).empty()) {
+                                    break;
+                                }
+                                const std::string& name = mesh->GetTextureCoordChannelName(i);
+                                if (name == uvSet) {
+                                    index = static_cast<int>(i);
+                                    break;
+                                }
+                            }
+                            if (index == -1) {
+                                FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material");
+                                continue;
+                            }
+
+                            if (uvIndex == -1) {
+                                uvIndex = index;
+                            }
+                            else {
+                                FBXImporter::LogWarn("the UV channel named " + uvSet + " appears at different positions in meshes, results will be wrong");
+                            }
+                        }
+                    }
+                    else
+                    {
+                        int index = -1;
+                        for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
+                            if (mesh->GetTextureCoords(i).empty()) {
+                                break;
+                            }
+                            const std::string& name = mesh->GetTextureCoordChannelName(i);
+                            if (name == uvSet) {
+                                index = static_cast<int>(i);
+                                break;
+                            }
+                        }
+                        if (index == -1) {
+                            FBXImporter::LogWarn("did not find UV channel named " + uvSet + " in a mesh using this material");
+                        }
+
+                        if (uvIndex == -1) {
+                            uvIndex = index;
+                        }
+                    }
+
+                    if (uvIndex == -1) {
+                        FBXImporter::LogWarn("failed to resolve UV channel " + uvSet + ", using first UV channel");
+                        uvIndex = 0;
+                    }
+                }
+            }
+
+            out_mat->AddProperty(&uvIndex, 1, (name + "|uvwsrc").c_str(), aiTextureType_UNKNOWN, 0);
+        }
             }
         }
 

+ 1 - 0
code/FBXConverter.h

@@ -268,6 +268,7 @@ private:
 
     // ------------------------------------------------------------------------------------------------
     void SetShadingPropertiesCommon(aiMaterial* out_mat, const PropertyTable& props);
+    void SetShadingPropertiesRaw(aiMaterial* out_mat, const PropertyTable& props, const TextureMap& textures, const MeshGeometry* const mesh);
 
     // ------------------------------------------------------------------------------------------------
     // get the number of fps for a FrameRate enumerated value