Browse Source

Merge branch 'master' into ETC_Inc

Kim Kulling 6 years ago
parent
commit
05ea039846
7 changed files with 288 additions and 4 deletions
  1. 1 1
      code/CMakeLists.txt
  2. 227 1
      code/FBXConverter.cpp
  3. 8 2
      code/FBXConverter.h
  4. 3 0
      code/FBXDocument.cpp
  5. 1 0
      code/FBXDocument.h
  6. 26 0
      code/FBXMeshGeometry.cpp
  7. 22 0
      code/FBXMeshGeometry.h

+ 1 - 1
code/CMakeLists.txt

@@ -890,7 +890,7 @@ SET( assimp_src
   ${PostProcessing_SRCS}
   ${MaterialSystem_SRCS}
   ${STEPParser_SRCS}
-  ${Step_SRCS}
+#  ${Step_SRCS} check if we need a different approach
 
   # Model Support
   ${ASSIMP_LOADER_SRCS}

+ 227 - 1
code/FBXConverter.cpp

@@ -870,10 +870,15 @@ namespace Assimp {
             for (const Geometry* geo : geos) {
 
                 const MeshGeometry* const mesh = dynamic_cast<const MeshGeometry*>(geo);
+                const LineGeometry* const line = dynamic_cast<const LineGeometry*>(geo);
                 if (mesh) {
                     const std::vector<unsigned int>& indices = ConvertMesh(*mesh, model, node_global_transform, nd);
                     std::copy(indices.begin(), indices.end(), std::back_inserter(meshes));
                 }
+                else if (line) {
+                    const std::vector<unsigned int>& indices = ConvertLine(*line, model, node_global_transform, nd);
+                    std::copy(indices.begin(), indices.end(), std::back_inserter(meshes));
+                }
                 else {
                     FBXImporter::LogWarn("ignoring unrecognized geometry: " + geo->Name());
                 }
@@ -922,7 +927,52 @@ namespace Assimp {
             return temp;
         }
 
-        aiMesh* FBXConverter::SetupEmptyMesh(const MeshGeometry& mesh, aiNode& nd)
+        std::vector<unsigned int> FBXConverter::ConvertLine(const LineGeometry& line, const Model& model,
+            const aiMatrix4x4& node_global_transform, aiNode& nd)
+        {
+            std::vector<unsigned int> temp;
+
+            const std::vector<aiVector3D>& vertices = line.GetVertices();
+            const std::vector<int>& indices = line.GetIndices();
+            if (vertices.empty() || indices.empty()) {
+                FBXImporter::LogWarn("ignoring empty line: " + line.Name());
+                return temp;
+            }
+
+            aiMesh* const out_mesh = SetupEmptyMesh(line, nd);
+            out_mesh->mPrimitiveTypes |= aiPrimitiveType_LINE;
+
+            // copy vertices
+            out_mesh->mNumVertices = static_cast<unsigned int>(vertices.size());
+            out_mesh->mVertices = new aiVector3D[out_mesh->mNumVertices];
+            std::copy(vertices.begin(), vertices.end(), out_mesh->mVertices);
+
+            //Number of line segments (faces) is "Number of Points - Number of Endpoints"
+            //N.B.: Endpoints in FbxLine are denoted by negative indices.
+            //If such an Index is encountered, add 1 and multiply by -1 to get the real index.
+            unsigned int epcount = 0;
+            for (unsigned i = 0; i < indices.size(); i++)
+            {
+                if (indices[i] < 0) epcount++;
+            }
+            unsigned int pcount = indices.size();
+            unsigned int scount = out_mesh->mNumFaces = pcount - epcount;
+
+            aiFace* fac = out_mesh->mFaces = new aiFace[scount]();
+            for (unsigned int i = 0; i < pcount; ++i) {
+                if (indices[i] < 0) continue;
+                aiFace& f = *fac++;
+                f.mNumIndices = 2; //2 == aiPrimitiveType_LINE 
+                f.mIndices = new unsigned int[2];
+                f.mIndices[0] = indices[i];
+                int segid = indices[(i + 1 == pcount ? 0 : i + 1)];   //If we have reached he last point, wrap around
+                f.mIndices[1] = (segid < 0 ? (segid + 1)*-1 : segid); //Convert EndPoint Index to normal Index
+            }
+            temp.push_back(static_cast<unsigned int>(meshes.size() - 1));
+            return temp;
+        }
+
+        aiMesh* FBXConverter::SetupEmptyMesh(const Geometry& mesh, aiNode& nd)
         {
             aiMesh* const out_mesh = new aiMesh();
             meshes.push_back(out_mesh);
@@ -957,6 +1007,7 @@ namespace Assimp {
             // copy vertices
             out_mesh->mNumVertices = static_cast<unsigned int>(vertices.size());
             out_mesh->mVertices = new aiVector3D[vertices.size()];
+
             std::copy(vertices.begin(), vertices.end(), out_mesh->mVertices);
 
             // generate dummy faces
@@ -1524,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);
@@ -2022,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);
+        }
             }
         }
 

+ 8 - 2
code/FBXConverter.h

@@ -174,14 +174,18 @@ private:
 
     // ------------------------------------------------------------------------------------------------
     void ConvertModel(const Model& model, aiNode& nd, const aiMatrix4x4& node_global_transform);
-
+    
     // ------------------------------------------------------------------------------------------------
     // MeshGeometry -> aiMesh, return mesh index + 1 or 0 if the conversion failed
     std::vector<unsigned int> ConvertMesh(const MeshGeometry& mesh, const Model& model,
         const aiMatrix4x4& node_global_transform, aiNode& nd);
 
     // ------------------------------------------------------------------------------------------------
-    aiMesh* SetupEmptyMesh(const MeshGeometry& mesh, aiNode& nd);
+    std::vector<unsigned int> ConvertLine(const LineGeometry& line, const Model& model,
+        const aiMatrix4x4& node_global_transform, aiNode& nd);
+
+    // ------------------------------------------------------------------------------------------------
+    aiMesh* SetupEmptyMesh(const Geometry& mesh, aiNode& nd);
 
     // ------------------------------------------------------------------------------------------------
     unsigned int ConvertMeshSingleMaterial(const MeshGeometry& mesh, const Model& model,
@@ -264,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
@@ -424,6 +429,7 @@ private:
     std::vector<aiLight*> lights;
     std::vector<aiCamera*> cameras;
     std::vector<aiTexture*> textures;
+    
 
     typedef std::map<const Material*, unsigned int> MaterialMap;
     MaterialMap materials_converted;

+ 3 - 0
code/FBXDocument.cpp

@@ -149,6 +149,9 @@ const Object* LazyObject::Get(bool dieOnError)
             if (!strcmp(classtag.c_str(), "Shape")) {
                 object.reset(new ShapeGeometry(id, element, name, doc));
             }
+            if (!strcmp(classtag.c_str(), "Line")) {
+                object.reset(new LineGeometry(id, element, name, doc));
+            }
         }
         else if (!strncmp(obtype,"NodeAttribute",length)) {
             if (!strcmp(classtag.c_str(),"Camera")) {

+ 1 - 0
code/FBXDocument.h

@@ -66,6 +66,7 @@ class PropertyTable;
 class Document;
 class Material;
 class ShapeGeometry;
+class LineGeometry;
 class Geometry;
 
 class Video;

+ 26 - 0
code/FBXMeshGeometry.cpp

@@ -679,6 +679,32 @@ const std::vector<aiVector3D>& ShapeGeometry::GetNormals() const {
 const std::vector<unsigned int>& ShapeGeometry::GetIndices() const {
     return m_indices;
 }
+// ------------------------------------------------------------------------------------------------
+LineGeometry::LineGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc)
+    : Geometry(id, element, name, doc)
+{
+    const Scope* sc = element.Compound();
+    if (!sc) {
+        DOMError("failed to read Geometry object (class: Line), no data scope found");
+    }
+    const Element& Points = GetRequiredElement(*sc, "Points", &element);
+    const Element& PointsIndex = GetRequiredElement(*sc, "PointsIndex", &element);
+    ParseVectorDataArray(m_vertices, Points);
+    ParseVectorDataArray(m_indices, PointsIndex);
+}
+
+// ------------------------------------------------------------------------------------------------
+LineGeometry::~LineGeometry() {
+    // empty
+}
+// ------------------------------------------------------------------------------------------------
+const std::vector<aiVector3D>& LineGeometry::GetVertices() const {
+    return m_vertices;
+}
+// ------------------------------------------------------------------------------------------------
+const std::vector<int>& LineGeometry::GetIndices() const {
+    return m_indices;
+}
 } // !FBX
 } // !Assimp
 #endif

+ 22 - 0
code/FBXMeshGeometry.h

@@ -205,6 +205,28 @@ private:
     std::vector<aiVector3D> m_normals;
     std::vector<unsigned int> m_indices;
 };
+/**
+*  DOM class for FBX geometry of type "Line"
+*/
+class LineGeometry : public Geometry
+{
+public:
+    /** The class constructor */
+    LineGeometry(uint64_t id, const Element& element, const std::string& name, const Document& doc);
+
+    /** The class destructor */
+    virtual ~LineGeometry();
+
+    /** Get a list of all vertex points, non-unique*/
+    const std::vector<aiVector3D>& GetVertices() const;
+
+    /** Return list of vertex indices. */
+    const std::vector<int>& GetIndices() const;
+
+private:
+    std::vector<aiVector3D> m_vertices;
+    std::vector<int> m_indices;
+};
 
 }
 }