2
0
Эх сурвалжийг харах

Merge branch 'master' into patch-1

Kim Kulling 2 жил өмнө
parent
commit
b6c0fdd6e0

+ 6 - 10
Dockerfile

@@ -1,14 +1,9 @@
-FROM ubuntu:14.04
+FROM ubuntu:22.04
 
-RUN apt-get update && apt-get install -y \
+RUN apt-get update && apt-get install -y ninja-build \
     git cmake build-essential software-properties-common
 
-RUN add-apt-repository ppa:ubuntu-toolchain-r/test && apt-get update && apt-get install -y gcc-4.9 g++-4.9 && \
-    cd /usr/bin && \
-    rm gcc g++ cpp && \
-    ln -s gcc-4.9 gcc && \
-    ln -s g++-4.9 g++ && \
-    ln -s cpp-4.9 cpp
+RUN add-apt-repository ppa:ubuntu-toolchain-r/test && apt-get update 
 
 WORKDIR /opt
 
@@ -19,7 +14,8 @@ WORKDIR /opt/assimp
 
 RUN git checkout master \
     && mkdir build && cd build && \
-    cmake \
+    cmake -G 'Ninja' \
     -DCMAKE_BUILD_TYPE=Release \
+    -DASSIMP_BUILD_ASSIMP_TOOLS=ON \
     .. && \
-    make && make install
+    ninja -j4 && ninja install

+ 7 - 3
code/AssetLib/Obj/ObjFileImporter.cpp

@@ -323,7 +323,7 @@ aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjF
         return nullptr;
     }
 
-    aiMesh *pMesh = new aiMesh;
+    std::unique_ptr<aiMesh> pMesh(new aiMesh);
     if (!pObjMesh->m_name.empty()) {
         pMesh->mName.Set(pObjMesh->m_name);
     }
@@ -385,9 +385,9 @@ aiMesh *ObjFileImporter::createTopology(const ObjFile::Model *pModel, const ObjF
     }
 
     // Create mesh vertices
-    createVertexArray(pModel, pData, meshIndex, pMesh, uiIdxCount);
+    createVertexArray(pModel, pData, meshIndex, pMesh.get(), uiIdxCount);
 
-    return pMesh;
+    return pMesh.release();
 }
 
 // ------------------------------------------------------------------------------------------------
@@ -498,6 +498,10 @@ void ObjFileImporter::createVertexArray(const ObjFile::Model *pModel,
 
                 if (vertexIndex) {
                     if (!last) {
+                        if (pMesh->mNumVertices <= newIndex + 1) {
+                            throw DeadlyImportError("OBJ: bad vertex index");
+                        }
+
                         pMesh->mVertices[newIndex + 1] = pMesh->mVertices[newIndex];
                         if (!sourceFace->m_normals.empty() && !pModel->mNormals.empty()) {
                             pMesh->mNormals[newIndex + 1] = pMesh->mNormals[newIndex];

+ 10 - 1
code/AssetLib/glTF2/glTF2Asset.h

@@ -371,6 +371,15 @@ struct CustomExtension {
     CustomExtension& operator=(const CustomExtension&) = default;
 };
 
+//! Represents metadata in an glTF2 object
+struct Extras {
+    std::vector<CustomExtension> mValues;
+
+    inline bool HasExtras() const {
+        return !mValues.empty();
+    }
+};
+
 //! Base class for all glTF top-level objects
 struct Object {
     int index; //!< The index of this object within its property container
@@ -379,7 +388,7 @@ struct Object {
     std::string name; //!< The user-defined name of this object
 
     CustomExtension customExtensions;
-    CustomExtension extras;
+    Extras extras;
 
     //! Objects marked as special are not exported (used to emulate the binary body buffer)
     virtual bool IsSpecial() const { return false; }

+ 13 - 1
code/AssetLib/glTF2/glTF2Asset.inl

@@ -139,6 +139,18 @@ inline CustomExtension ReadExtensions(const char *name, Value &obj) {
     return ret;
 }
 
+inline Extras ReadExtras(Value &obj) {
+    Extras ret;
+
+    ret.mValues.reserve(obj.MemberCount());
+    for (auto it = obj.MemberBegin(); it != obj.MemberEnd(); ++it) {
+        auto &val = it->value;
+        ret.mValues.emplace_back(ReadExtensions(it->name.GetString(), val));
+    }
+
+    return ret;
+}
+
 inline void CopyData(size_t count, const uint8_t *src, size_t src_stride,
         uint8_t *dst, size_t dst_stride) {
     if (src_stride == dst_stride) {
@@ -248,7 +260,7 @@ inline void Object::ReadExtensions(Value &val) {
 
 inline void Object::ReadExtras(Value &val) {
     if (Value *curExtras = FindObject(val, "extras")) {
-        this->extras = glTF2::ReadExtensions("extras", *curExtras);
+        this->extras = glTF2::ReadExtras(*curExtras);
     }
 }
 

+ 40 - 1
code/AssetLib/glTF2/glTF2AssetWriter.inl

@@ -654,6 +654,44 @@ namespace glTF2 {
         }
     }
 
+    inline void WriteExtrasValue(Value &parent, const CustomExtension &value, AssetWriter &w) {
+        Value valueNode;
+
+        if (value.mStringValue.isPresent) {
+            MakeValue(valueNode, value.mStringValue.value.c_str(), w.mAl);
+        } else if (value.mDoubleValue.isPresent) {
+            MakeValue(valueNode, value.mDoubleValue.value, w.mAl);
+        } else if (value.mUint64Value.isPresent) {
+            MakeValue(valueNode, value.mUint64Value.value, w.mAl);
+        } else if (value.mInt64Value.isPresent) {
+            MakeValue(valueNode, value.mInt64Value.value, w.mAl);
+        } else if (value.mBoolValue.isPresent) {
+            MakeValue(valueNode, value.mBoolValue.value, w.mAl);
+        } else if (value.mValues.isPresent) {
+            valueNode.SetObject();
+            for (auto const &subvalue : value.mValues.value) {
+                WriteExtrasValue(valueNode, subvalue, w);
+            }
+        }
+
+        parent.AddMember(StringRef(value.name), valueNode, w.mAl);
+    }
+
+    inline void WriteExtras(Value &obj, const Extras &extras, AssetWriter &w) {
+        if (!extras.HasExtras()) {
+            return;
+        }
+
+        Value extrasNode;
+        extrasNode.SetObject();
+
+        for (auto const &value : extras.mValues) {
+            WriteExtrasValue(extrasNode, value, w);
+        }
+        
+        obj.AddMember("extras", extrasNode, w.mAl);
+    }
+
     inline void Write(Value& obj, Node& n, AssetWriter& w)
     {
         if (n.matrix.isPresent) {
@@ -689,6 +727,8 @@ namespace glTF2 {
         if(n.skeletons.size()) {
             AddRefsVector(obj, "skeletons", n.skeletons, w.mAl);
         }
+
+        WriteExtras(obj, n.extras, w);
     }
 
     inline void Write(Value& /*obj*/, Program& /*b*/, AssetWriter& /*w*/)
@@ -762,7 +802,6 @@ namespace glTF2 {
         }
     }
 
-
     inline AssetWriter::AssetWriter(Asset& a)
         : mDoc()
         , mAsset(a)

+ 58 - 1
code/AssetLib/glTF2/glTF2Exporter.cpp

@@ -443,6 +443,61 @@ inline Ref<Accessor> ExportData(Asset &a, std::string &meshName, Ref<Buffer> &bu
     return acc;
 }
 
+inline void ExportNodeExtras(const aiMetadataEntry &metadataEntry, aiString name, CustomExtension &value) {
+
+    value.name = name.C_Str();
+    switch (metadataEntry.mType) {
+    case AI_BOOL:
+        value.mBoolValue.value = *static_cast<bool *>(metadataEntry.mData);
+        value.mBoolValue.isPresent = true;
+        break;
+    case AI_INT32:
+        value.mInt64Value.value = *static_cast<int32_t *>(metadataEntry.mData);
+        value.mInt64Value.isPresent = true;
+        break;
+    case AI_UINT64:
+        value.mUint64Value.value = *static_cast<uint64_t *>(metadataEntry.mData);
+        value.mUint64Value.isPresent = true;
+        break;
+    case AI_FLOAT:
+        value.mDoubleValue.value = *static_cast<float *>(metadataEntry.mData);
+        value.mDoubleValue.isPresent = true;
+        break;
+    case AI_DOUBLE:
+        value.mDoubleValue.value = *static_cast<double *>(metadataEntry.mData);
+        value.mDoubleValue.isPresent = true;
+        break;
+    case AI_AISTRING:
+        value.mStringValue.value = static_cast<aiString *>(metadataEntry.mData)->C_Str();
+        value.mStringValue.isPresent = true;
+        break;
+    case AI_AIMETADATA: {
+        const aiMetadata *subMetadata = static_cast<aiMetadata *>(metadataEntry.mData);
+        value.mValues.value.resize(subMetadata->mNumProperties);
+        value.mValues.isPresent = true;
+
+        for (unsigned i = 0; i < subMetadata->mNumProperties; ++i) {
+            ExportNodeExtras(subMetadata->mValues[i], subMetadata->mKeys[i], value.mValues.value.at(i));
+        }
+        break;
+    }
+    default:
+        // AI_AIVECTOR3D not handled
+        break;
+    }
+}
+
+inline void ExportNodeExtras(const aiMetadata *metadata, Extras &extras) {
+    if (metadata == nullptr || metadata->mNumProperties == 0) {
+        return;
+    }
+
+    extras.mValues.resize(metadata->mNumProperties);
+    for (unsigned int i = 0; i < metadata->mNumProperties; ++i) {
+        ExportNodeExtras(metadata->mValues[i], metadata->mKeys[i], extras.mValues.at(i));
+    }
+}
+
 inline void SetSamplerWrap(SamplerWrap &wrap, aiTextureMapMode map) {
     switch (map) {
     case aiTextureMapMode_Clamp:
@@ -1375,7 +1430,7 @@ unsigned int glTF2Exporter::ExportNodeHierarchy(const aiNode *n) {
     return node.GetIndex();
 }
 
-/*
+ /*
  * Export node and recursively calls ExportNode for all children.
  * Since these nodes are not the root node, we also export the parent Ref<Node>
  */
@@ -1386,6 +1441,8 @@ unsigned int glTF2Exporter::ExportNode(const aiNode *n, Ref<Node> &parent) {
     node->parent = parent;
     node->name = name;
 
+    ExportNodeExtras(n->mMetaData, node->extras);
+
     if (!n->mTransformation.IsIdentity()) {
         if (mScene->mNumAnimations > 0 || (mProperties && mProperties->HasPropertyBool("GLTF2_NODE_IN_TRS"))) {
             aiQuaternion quaternion;

+ 5 - 7
code/AssetLib/glTF2/glTF2Importer.cpp

@@ -1103,11 +1103,9 @@ void ParseExtensions(aiMetadata *metadata, const CustomExtension &extension) {
     }
 }
 
-void ParseExtras(aiMetadata *metadata, const CustomExtension &extension) {
-    if (extension.mValues.isPresent) {
-        for (auto const &subExtension : extension.mValues.value) {
-            ParseExtensions(metadata, subExtension);
-        }
+void ParseExtras(aiMetadata* metadata, const Extras& extras) {
+    for (auto const &value : extras.mValues) {
+        ParseExtensions(metadata, value);
     }
 }
 
@@ -1129,12 +1127,12 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
             }
         }
 
-        if (node.customExtensions || node.extras) {
+        if (node.customExtensions || node.extras.HasExtras()) {
             ainode->mMetaData = new aiMetadata;
             if (node.customExtensions) {
                 ParseExtensions(ainode->mMetaData, node.customExtensions);
             }
-            if (node.extras) {
+            if (node.extras.HasExtras()) {
                 ParseExtras(ainode->mMetaData, node.extras);
             }
         }

+ 1 - 2
code/CMakeLists.txt

@@ -1200,7 +1200,6 @@ IF (ASSIMP_WARNINGS_AS_ERRORS)
 
     IF(CMAKE_CXX_COMPILER_ID MATCHES "Clang" ) # clang-cl
       TARGET_COMPILE_OPTIONS(assimp PRIVATE -Wall -Werror
-        -Wno-unused-function
         -Wno-microsoft-enum-value
         -Wno-switch-enum
         -Wno-covered-switch-default
@@ -1390,7 +1389,7 @@ ENDIF()
 
 # Add RT-extension library for glTF importer with Open3DGC-compression.
 IF (RT_FOUND AND ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC)
-  TARGET_LINK_LIBRARIES(assimp ${RT_LIBRARY})
+  TARGET_LINK_LIBRARIES(assimp rt)
 ENDIF ()
 
 

+ 1 - 1
code/Common/Exporter.cpp

@@ -225,7 +225,7 @@ static void setupExporterArray(std::vector<Exporter::ExportFormatEntry> &exporte
 #endif
 
 #ifndef ASSIMP_BUILD_NO_PBRT_EXPORTER
-	exporters.emplace_back("pbrt", "pbrt-v4 scene description file", "pbrt", &ExportScenePbrt, aiProcess_Triangulate | aiProcess_SortByPType);
+	exporters.emplace_back("pbrt", "pbrt-v4 scene description file", "pbrt", &ExportScenePbrt, aiProcess_ConvertToLeftHanded | aiProcess_Triangulate | aiProcess_SortByPType);
 #endif
 
 #ifndef ASSIMP_BUILD_NO_ASSJSON_EXPORTER

+ 8 - 0
code/Common/StbCommon.h

@@ -48,6 +48,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #pragma GCC diagnostic ignored "-Wunused-function"
 #endif
 
+#if defined(__clang__)
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wunused-function"
+#endif
+
 #ifndef STB_USE_HUNTER
 /*  Use prefixed names for the symbols from stb_image as it is a very commonly embedded library.
     Including vanilla stb_image symbols causes duplicate symbol problems if assimp is linked
@@ -114,3 +119,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #pragma GCC diagnostic pop
 #endif
 
+#if defined(__clang__)
+#pragma clang diagnostic pop
+#endif

+ 21 - 6
code/Pbrt/PbrtExporter.cpp

@@ -111,7 +111,22 @@ PbrtExporter::PbrtExporter(
         mScene(pScene),
         mIOSystem(pIOSystem),
         mPath(path),
-        mFile(file) {
+        mFile(file),
+        mRootTransform(
+            // rotates the (already left-handed) CRS -90 degrees around the x axis in order to
+            // make +Z 'up' and +Y 'towards viewer', as in default in pbrt
+            1.f,  0.f,  0.f, 0.f, //
+            0.f,  0.f, -1.f, 0.f, //
+            0.f,  1.f,  0.f, 0.f, //
+            0.f,  0.f,  0.f, 1.f  //
+        ) {
+
+    mRootTransform = aiMatrix4x4(
+        -1.f,  0,  0.f, 0.f, //
+        0.0f,  -1.f,  0.f, 0.f, //
+        0.f,  0.f,  1.f, 0.f, //
+        0.f,  0.f,  0.f, 1.f  //
+    ) * mRootTransform;
     // Export embedded textures.
     if (mScene->mNumTextures > 0)
         if (!mIOSystem->CreateDirectory("textures"))
@@ -260,7 +275,7 @@ aiMatrix4x4 PbrtExporter::GetNodeTransform(const aiString &name) const {
             node = node->mParent;
         }
     }
-    return m;
+    return mRootTransform * m;
 }
 
 std::string PbrtExporter::TransformAsString(const aiMatrix4x4 &m) {
@@ -309,7 +324,7 @@ void PbrtExporter::WriteCamera(int i) {
 
     // Get camera fov
     float hfov = AI_RAD_TO_DEG(camera->mHorizontalFOV);
-    float fov = (aspect >= 1.0) ? hfov : (hfov * aspect);
+    float fov = (aspect >= 1.0) ? hfov : (hfov / aspect);
     if (fov < 5) {
         std::cerr << fov << ": suspiciously low field of view specified by camera. Setting to 45 degrees.\n";
         fov = 45;
@@ -327,7 +342,7 @@ void PbrtExporter::WriteCamera(int i) {
 
     if (!cameraActive)
         mOutput << "# ";
-    mOutput << "Scale -1 1 1\n";  // right handed -> left handed
+    mOutput << "Scale 1 1 1\n";
     if (!cameraActive)
         mOutput << "# ";
     mOutput << "LookAt "
@@ -383,8 +398,8 @@ void PbrtExporter::WriteWorldDefinition() {
     }
 
     mOutput << "# Geometry\n\n";
-    aiMatrix4x4 worldFromObject;
-    WriteGeometricObjects(mScene->mRootNode, worldFromObject, meshUses);
+
+    WriteGeometricObjects(mScene->mRootNode, mRootTransform, meshUses);
 }
 
 void PbrtExporter::WriteTextures() {

+ 3 - 0
code/Pbrt/PbrtExporter.h

@@ -100,6 +100,9 @@ private:
     //  A private set to keep track of which textures have been declared
     std::set<std::string> mTextureSet;
 
+    // Transform to apply to the root node and all root objects such as cameras, lights, etc.
+    aiMatrix4x4 mRootTransform;
+
     aiMatrix4x4 GetNodeTransform(const aiString& name) const;
     static std::string TransformAsString(const aiMatrix4x4& m);