diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
index e0c2bec9e..84e3123fe 100644
--- a/.github/FUNDING.yml
+++ b/.github/FUNDING.yml
@@ -1,2 +1,3 @@
patreon: assimp
custom: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=4JRJVPXC4QJM4
+open_collective: assimp
diff --git a/.github/workflows/ccpp.yml b/.github/workflows/ccpp.yml
index 60bfba170..08292d55f 100644
--- a/.github/workflows/ccpp.yml
+++ b/.github/workflows/ccpp.yml
@@ -7,40 +7,53 @@ on:
branches: [ master ]
jobs:
- linux:
- runs-on: ubuntu-latest
-
- steps:
- - uses: actions/checkout@v2
- - name: configure
- run: cmake CMakeLists.txt
- - name: build
- run: cmake --build .
- - name: test
- run: cd bin && ./unit
-
- mac:
- runs-on: macos-latest
-
- steps:
- - uses: actions/checkout@v2
- - name: configure
- run: cmake CMakeLists.txt
- - name: build
- run: cmake --build .
- - name: test
- run: cd bin && ./unit
+ job:
+ name: ${{ matrix.os }}-${{ matrix.cxx }}-build-and-test
+ runs-on: ${{ matrix.os }}
+ strategy:
+ fail-fast: false
+ matrix:
+ name: [ubuntu-gcc, macos-clang, windows-msvc, ubuntu-clang]
+ # For Windows msvc, for Linux and macOS let's use the clang compiler, use gcc for Linux.
+ include:
+ - name: windows-msvc
+ os: windows-latest
+ cxx: cl.exe
+ cc: cl.exe
+ - name: ubuntu-clang
+ os: ubuntu-latest
+ cxx: clang++
+ cc: clang
+ - name: macos-clang
+ os: macos-latest
+ cxx: clang++
+ cc: clang
+ - name: ubuntu-gcc
+ os: ubuntu-latest
+ cxx: g++
+ cc: gcc
- windows:
- runs-on: windows-latest
-
steps:
- uses: actions/checkout@v2
- - name: configure
- run: cmake CMakeLists.txt
- - name: build
- run: cmake --build . --config Release
+
+ - uses: lukka/get-cmake@latest
+
+ - uses: ilammy/msvc-dev-cmd@v1
+
+ - uses: lukka/set-shell-env@v1
+ with:
+ CXX: ${{ matrix.cxx }}
+ CC: ${{ matrix.cc }}
+
+ - name: configure and build
+ uses: lukka/run-cmake@v2
+ with:
+ cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
+ cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt'
+ cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Release'
+ buildWithCMakeArgs: '-- -v'
+ buildDirectory: '${{ github.workspace }}/build/'
+
- name: test
- run: |
- cd bin\Release
- .\unit
+ run: cd build/bin && ./unit
+ shell: bash
diff --git a/.github/workflows/sanitizer.yml b/.github/workflows/sanitizer.yml
new file mode 100644
index 000000000..9bba5f6fd
--- /dev/null
+++ b/.github/workflows/sanitizer.yml
@@ -0,0 +1,56 @@
+name: C/C++ Sanitizer
+
+on:
+ push:
+ branches: [ master ]
+ pull_request:
+ branches: [ master ]
+
+jobs:
+ job1:
+ name: adress-sanitizer
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: lukka/get-cmake@latest
+ - uses: lukka/set-shell-env@v1
+ with:
+ CXX: clang++
+ CC: clang
+
+ - name: configure and build
+ uses: lukka/run-cmake@v2
+ with:
+ cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
+ cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt'
+ cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Debug -DASSIMP_ASAN=ON'
+ buildWithCMakeArgs: '-- -v'
+ buildDirectory: '${{ github.workspace }}/build/'
+
+ - name: test
+ run: cd build/bin && ./unit
+ shell: bash
+
+ job2:
+ name: undefined-behavior-sanitizer
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - uses: lukka/get-cmake@latest
+ - uses: lukka/set-shell-env@v1
+ with:
+ CXX: clang++
+ CC: clang
+
+ - name: configure and build
+ uses: lukka/run-cmake@v2
+ with:
+ cmakeListsOrSettingsJson: CMakeListsTxtAdvanced
+ cmakeListsTxtPath: '${{ github.workspace }}/CMakeLists.txt'
+ cmakeAppendedArgs: '-GNinja -DCMAKE_BUILD_TYPE=Debug -DASSIMP_UBSAN=ON'
+ buildWithCMakeArgs: '-- -v'
+ buildDirectory: '${{ github.workspace }}/build/'
+
+ - name: test
+ run: cd build/bin && ./unit
+ shell: bash
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 640f89e64..6b350f6e3 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -108,10 +108,6 @@ OPTION ( ASSIMP_ERROR_MAX
"Enable all warnings."
OFF
)
-OPTION ( ASSIMP_WERROR
- "Treat warnings as errors."
- OFF
-)
OPTION ( ASSIMP_ASAN
"Enable AddressSanitizer."
OFF
@@ -138,6 +134,12 @@ OPTION ( ASSIMP_IGNORE_GIT_HASH
OFF
)
+IF ( WIN32 )
+ OPTION ( ASSIMP_BUILD_ASSIMP_VIEW
+ "If the Assimp view tool is built. (requires DirectX)"
+ OFF )
+ENDIF()
+
IF (IOS AND NOT ASSIMP_HUNTER_ENABLED)
IF (NOT CMAKE_BUILD_TYPE)
SET(CMAKE_BUILD_TYPE "Release")
@@ -238,14 +240,19 @@ SET(LIBASSIMP-DEV_COMPONENT "libassimp${ASSIMP_VERSION_MAJOR}.${ASSIMP_VERSION_M
SET(CPACK_COMPONENTS_ALL assimp-bin ${LIBASSIMP_COMPONENT} ${LIBASSIMP-DEV_COMPONENT} assimp-dev)
SET(ASSIMP_LIBRARY_SUFFIX "" CACHE STRING "Suffix to append to library names")
-# Grouped compiler settings
+IF( UNIX )
+ # Use GNUInstallDirs for Unix predefined directories
+ INCLUDE(GNUInstallDirs)
+ENDIF()
+
+# Grouped compiler settings ########################################
IF ((CMAKE_C_COMPILER_ID MATCHES "GNU") AND NOT CMAKE_COMPILER_IS_MINGW)
IF(NOT ASSIMP_HUNTER_ENABLED)
- SET(CMAKE_CXX_FLAGS "-fPIC -std=c++0x ${CMAKE_CXX_FLAGS}")
- SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
+ SET(CMAKE_CXX_STANDARD 11)
+ SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
ENDIF()
# hide all not-exported symbols
- SET(CMAKE_CXX_FLAGS "-g -fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
+ SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall ${CMAKE_CXX_FLAGS}")
SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
SET(LIBSTDC++_LIBRARIES -lstdc++)
ELSEIF(MSVC)
@@ -258,10 +265,10 @@ ELSEIF(MSVC)
SET(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} /D_DEBUG /Zi /Od")
ELSEIF ( "${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang" )
IF(NOT ASSIMP_HUNTER_ENABLED)
- SET(CMAKE_CXX_FLAGS "-fPIC -std=c++11 ${CMAKE_CXX_FLAGS}")
- SET(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}")
+ SET(CMAKE_CXX_STANDARD 11)
+ SET(CMAKE_POSITION_INDEPENDENT_CODE ON)
ENDIF()
- SET(CMAKE_CXX_FLAGS "-g -fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" )
+ SET(CMAKE_CXX_FLAGS "-fvisibility=hidden -fno-strict-aliasing -Wall -Wno-long-long ${CMAKE_CXX_FLAGS}" )
SET(CMAKE_C_FLAGS "-fno-strict-aliasing ${CMAKE_C_FLAGS}")
ELSEIF( CMAKE_COMPILER_IS_MINGW )
IF (CMAKE_CXX_COMPILER_VERSION VERSION_LESS 7.0)
@@ -306,16 +313,6 @@ IF (ASSIMP_ERROR_MAX)
ENDIF()
ENDIF()
-IF (ASSIMP_WERROR)
- MESSAGE(STATUS "Treating warnings as errors")
- IF (MSVC)
- ADD_COMPILE_OPTIONS(/WX)
- ELSE()
- SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Werror")
- SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror")
- ENDIF()
-ENDIF()
-
IF (ASSIMP_ASAN)
MESSAGE(STATUS "AddressSanitizer enabled")
SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address")
@@ -521,19 +518,19 @@ ENDIF()
SET ( ASSIMP_BUILD_ARCHITECTURE "" CACHE STRING
"describe the current architecture."
)
-IF ( ASSIMP_BUILD_ARCHITECTURE STREQUAL "")
-ELSE ()
+IF( ASSIMP_BUILD_ARCHITECTURE STREQUAL "")
+ELSE()
ADD_DEFINITIONS ( -D'ASSIMP_BUILD_ARCHITECTURE="${ASSIMP_BUILD_ARCHITECTURE}"' )
-ENDIF ()
+ENDIF()
# ${CMAKE_GENERATOR}
SET ( ASSIMP_BUILD_COMPILER "" CACHE STRING
"describe the current compiler."
)
-IF ( ASSIMP_BUILD_COMPILER STREQUAL "")
-ELSE ()
+IF( ASSIMP_BUILD_COMPILER STREQUAL "")
+ELSE()
ADD_DEFINITIONS ( -D'ASSIMP_BUILD_COMPILER="${ASSIMP_BUILD_COMPILER}"' )
-ENDIF ()
+ENDIF()
MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER )
diff --git a/INSTALL b/INSTALL
index 350a5f109..ecec2585b 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,50 +1,50 @@
-
-========================================================================
-Open Asset Import Library (assimp) INSTALL
-========================================================================
-
-------------------------------
-Getting the documentation
-------------------------------
-
-A regularly-updated copy is available at
-http://assimp.sourceforge.net/lib_html/index.html
-
-A CHM file is included in the SVN repos: ./doc/AssimpDoc_Html/AssimpDoc.chm.
-To build the doxygen documentation on your own, follow these steps:
-
-a) download & install latest doxygen
-b) make sure doxygen is in the executable search path
-c) navigate to ./doc
-d) and run 'doxygen'
-
-Open the generated HTML (AssimpDoc_Html/index.html) in the browser of your choice.
-Windows only: To generate the CHM doc, install 'Microsoft HTML Workshop'
-and configure the path to it in the DOXYFILE first.
-
-------------------------------
-Building Assimp
-------------------------------
-
-More detailed build instructions can be found in the documentation,
-this section is just for the inpatient among you.
-
-CMake is the preferred build system for Assimp. The minimum required version
-is 2.6. If you don't have it yet, downloads for CMake can be found on
-http://www.cmake.org/.
-
-For Unix:
-
-1. mkdir build && cd build
-2. cmake .. -G 'Unix Makefiles'
-3. make -j4
-
-For Windows:
-1. Open a command prompt
-2. mkdir build
-3. cd build
-4. cmake ..
-5. cmake --build .
-
-For iOS:
-Just check the following project, which deploys a compiler toolchain for different iOS-versions: https://github.com/assimp/assimp/tree/master/port/iOS
+
+========================================================================
+Open Asset Import Library (assimp) INSTALL
+========================================================================
+
+------------------------------
+Getting the documentation
+------------------------------
+
+A regularly-updated copy is available at
+http://assimp.sourceforge.net/lib_html/index.html
+
+A CHM file is included in the SVN repos: ./doc/AssimpDoc_Html/AssimpDoc.chm.
+To build the doxygen documentation on your own, follow these steps:
+
+a) download & install latest doxygen
+b) make sure doxygen is in the executable search path
+c) navigate to ./doc
+d) and run 'doxygen'
+
+Open the generated HTML (AssimpDoc_Html/index.html) in the browser of your choice.
+Windows only: To generate the CHM doc, install 'Microsoft HTML Workshop'
+and configure the path to it in the DOXYFILE first.
+
+------------------------------
+Building Assimp
+------------------------------
+
+More detailed build instructions can be found in the documentation,
+this section is just for the inpatient among you.
+
+CMake is the preferred build system for Assimp. The minimum required version
+is 2.6. If you don't have it yet, downloads for CMake can be found on
+http://www.cmake.org/.
+
+For Unix:
+
+1. mkdir build && cd build
+2. cmake .. -G 'Unix Makefiles'
+3. make -j4
+
+For Windows:
+1. Open a command prompt
+2. mkdir build
+3. cd build
+4. cmake ..
+5. cmake --build .
+
+For iOS:
+Just check the following project, which deploys a compiler toolchain for different iOS-versions: https://github.com/assimp/assimp/tree/master/port/iOS
diff --git a/Readme.md b/Readme.md
index 61fff538f..15e76b9d2 100644
--- a/Readme.md
+++ b/Readme.md
@@ -2,6 +2,7 @@ Open Asset Import Library (assimp)
==================================
A library to import and export various 3d-model-formats including scene-post-processing to generate missing render data.
### Current project status ###
+[![Financial Contributors on Open Collective](https://opencollective.com/assimp/all/badge.svg?label=financial+contributors)](https://opencollective.com/assimp)
![C/C++ CI](https://github.com/assimp/assimp/workflows/C/C++%20CI/badge.svg)
[![Linux Build Status](https://travis-ci.org/assimp/assimp.svg)](https://travis-ci.org/assimp/assimp)
[![Windows Build Status](https://ci.appveyor.com/api/projects/status/tmo433wax6u6cjp4?svg=true)](https://ci.appveyor.com/project/kimkulling/assimp)
@@ -179,6 +180,28 @@ And we also have a Gitter-channel:Gitter [![Join the chat at https://gitter.im/a
Contributions to assimp are highly appreciated. The easiest way to get involved is to submit
a pull request with your changes against the main repository's `master` branch.
+## Contributors
+
+### Code Contributors
+
+This project exists thanks to all the people who contribute. [[Contribute](CONTRIBUTING.md)].
+
+
+
+### Financial Contributors
+
+Become a financial contributor and help us sustain our community. [[Contribute](https://opencollective.com/assimp/contribute)]
+
+#### Individuals
+
+
+
+#### Organizations
+
+Support this project with your organization. Your logo will show up here with a link to your website. [[Contribute](https://opencollective.com/assimp/contribute)]
+
+
+
### License ###
Our license is based on the modified, __3-clause BSD__-License.
diff --git a/code/AMF/AMFImporter.cpp b/code/AMF/AMFImporter.cpp
deleted file mode 100644
index df4324d4d..000000000
--- a/code/AMF/AMFImporter.cpp
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
----------------------------------------------------------------------------
-Open Asset Import Library (assimp)
----------------------------------------------------------------------------
-
-Copyright (c) 2006-2020, assimp team
-
-
-
-All rights reserved.
-
-Redistribution and use of this software in source and binary forms,
-with or without modification, are permitted provided that the following
-conditions are met:
-
-* Redistributions of source code must retain the above
-copyright notice, this list of conditions and the
-following disclaimer.
-
-* Redistributions in binary form must reproduce the above
-copyright notice, this list of conditions and the
-following disclaimer in the documentation and/or other
-materials provided with the distribution.
-
-* Neither the name of the assimp team, nor the names of its
-contributors may be used to endorse or promote products
-derived from this software without specific prior
-written permission of the assimp team.
-
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------------
-*/
-
-/// \file AMFImporter.cpp
-/// \brief AMF-format files importer for Assimp: main algorithm implementation.
-/// \date 2016
-/// \author smal.root@gmail.com
-
-#ifndef ASSIMP_BUILD_NO_AMF_IMPORTER
-
-// Header files, Assimp.
-#include "AMFImporter.hpp"
-#include "AMFImporter_Macro.hpp"
-
-#include
-#include
-
-// Header files, stdlib.
-#include
-
-namespace Assimp
-{
-
-/// \var aiImporterDesc AMFImporter::Description
-/// Conastant which hold importer description
-const aiImporterDesc AMFImporter::Description = {
- "Additive manufacturing file format(AMF) Importer",
- "smalcom",
- "",
- "See documentation in source code. Chapter: Limitations.",
- aiImporterFlags_SupportTextFlavour | aiImporterFlags_LimitedSupport | aiImporterFlags_Experimental,
- 0,
- 0,
- 0,
- 0,
- "amf"
-};
-
-void AMFImporter::Clear()
-{
- mNodeElement_Cur = nullptr;
- mUnit.clear();
- mMaterial_Converted.clear();
- mTexture_Converted.clear();
- // Delete all elements
- if(!mNodeElement_List.empty())
- {
- for(CAMFImporter_NodeElement* ne: mNodeElement_List) { delete ne; }
-
- mNodeElement_List.clear();
- }
-}
-
-AMFImporter::~AMFImporter()
-{
- if(mReader != nullptr) delete mReader;
- // Clear() is accounting if data already is deleted. So, just check again if all data is deleted.
- Clear();
-}
-
-/*********************************************************************************************************************************************/
-/************************************************************ Functions: find set ************************************************************/
-/*********************************************************************************************************************************************/
-
-bool AMFImporter::Find_NodeElement(const std::string& pID, const CAMFImporter_NodeElement::EType pType, CAMFImporter_NodeElement** pNodeElement) const
-{
- for(CAMFImporter_NodeElement* ne: mNodeElement_List)
- {
- if((ne->ID == pID) && (ne->Type == pType))
- {
- if(pNodeElement != nullptr) *pNodeElement = ne;
-
- return true;
- }
- }// for(CAMFImporter_NodeElement* ne: mNodeElement_List)
-
- return false;
-}
-
-bool AMFImporter::Find_ConvertedNode(const std::string& pID, std::list& pNodeList, aiNode** pNode) const
-{
-aiString node_name(pID.c_str());
-
- for(aiNode* node: pNodeList)
- {
- if(node->mName == node_name)
- {
- if(pNode != nullptr) *pNode = node;
-
- return true;
- }
- }// for(aiNode* node: pNodeList)
-
- return false;
-}
-
-bool AMFImporter::Find_ConvertedMaterial(const std::string& pID, const SPP_Material** pConvertedMaterial) const
-{
- for(const SPP_Material& mat: mMaterial_Converted)
- {
- if(mat.ID == pID)
- {
- if(pConvertedMaterial != nullptr) *pConvertedMaterial = &mat;
-
- return true;
- }
- }// for(const SPP_Material& mat: mMaterial_Converted)
-
- return false;
-}
-
-/*********************************************************************************************************************************************/
-/************************************************************ Functions: throw set ***********************************************************/
-/*********************************************************************************************************************************************/
-
-void AMFImporter::Throw_CloseNotFound(const std::string& pNode)
-{
- throw DeadlyImportError("Close tag for node <" + pNode + "> not found. Seems file is corrupt.");
-}
-
-void AMFImporter::Throw_IncorrectAttr(const std::string& pAttrName)
-{
- throw DeadlyImportError("Node <" + std::string(mReader->getNodeName()) + "> has incorrect attribute \"" + pAttrName + "\".");
-}
-
-void AMFImporter::Throw_IncorrectAttrValue(const std::string& pAttrName)
-{
- throw DeadlyImportError("Attribute \"" + pAttrName + "\" in node <" + std::string(mReader->getNodeName()) + "> has incorrect value.");
-}
-
-void AMFImporter::Throw_MoreThanOnceDefined(const std::string& pNodeType, const std::string& pDescription)
-{
- throw DeadlyImportError("\"" + pNodeType + "\" node can be used only once in " + mReader->getNodeName() + ". Description: " + pDescription);
-}
-
-void AMFImporter::Throw_ID_NotFound(const std::string& pID) const
-{
- throw DeadlyImportError("Not found node with name \"" + pID + "\".");
-}
-
-/*********************************************************************************************************************************************/
-/************************************************************* Functions: XML set ************************************************************/
-/*********************************************************************************************************************************************/
-
-void AMFImporter::XML_CheckNode_MustHaveChildren()
-{
- if(mReader->isEmptyElement()) throw DeadlyImportError(std::string("Node <") + mReader->getNodeName() + "> must have children.");
-}
-
-void AMFImporter::XML_CheckNode_SkipUnsupported(const std::string& pParentNodeName)
-{
- static const size_t Uns_Skip_Len = 3;
- const char* Uns_Skip[Uns_Skip_Len] = { "composite", "edge", "normal" };
-
- static bool skipped_before[Uns_Skip_Len] = { false, false, false };
-
- std::string nn(mReader->getNodeName());
- bool found = false;
- bool close_found = false;
- size_t sk_idx;
-
- for(sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++)
- {
- if(nn != Uns_Skip[sk_idx]) continue;
-
- found = true;
- if(mReader->isEmptyElement())
- {
- close_found = true;
-
- goto casu_cres;
- }
-
- while(mReader->read())
- {
- if((mReader->getNodeType() == irr::io::EXN_ELEMENT_END) && (nn == mReader->getNodeName()))
- {
- close_found = true;
-
- goto casu_cres;
- }
- }
- }// for(sk_idx = 0; sk_idx < Uns_Skip_Len; sk_idx++)
-
-casu_cres:
-
- if(!found) throw DeadlyImportError("Unknown node \"" + nn + "\" in " + pParentNodeName + ".");
- if(!close_found) Throw_CloseNotFound(nn);
-
- if(!skipped_before[sk_idx])
- {
- skipped_before[sk_idx] = true;
- ASSIMP_LOG_WARN_F("Skipping node \"", nn, "\" in ", pParentNodeName, ".");
- }
-}
-
-bool AMFImporter::XML_SearchNode(const std::string& pNodeName)
-{
- while(mReader->read())
- {
- if((mReader->getNodeType() == irr::io::EXN_ELEMENT) && XML_CheckNode_NameEqual(pNodeName)) return true;
- }
-
- return false;
-}
-
-bool AMFImporter::XML_ReadNode_GetAttrVal_AsBool(const int pAttrIdx)
-{
- std::string val(mReader->getAttributeValue(pAttrIdx));
-
- if((val == "false") || (val == "0"))
- return false;
- else if((val == "true") || (val == "1"))
- return true;
- else
- throw DeadlyImportError("Bool attribute value can contain \"false\"/\"0\" or \"true\"/\"1\" not the \"" + val + "\"");
-}
-
-float AMFImporter::XML_ReadNode_GetAttrVal_AsFloat(const int pAttrIdx)
-{
- std::string val;
- float tvalf;
-
- ParseHelper_FixTruncatedFloatString(mReader->getAttributeValue(pAttrIdx), val);
- fast_atoreal_move(val.c_str(), tvalf, false);
-
- return tvalf;
-}
-
-uint32_t AMFImporter::XML_ReadNode_GetAttrVal_AsU32(const int pAttrIdx)
-{
- return strtoul10(mReader->getAttributeValue(pAttrIdx));
-}
-
-float AMFImporter::XML_ReadNode_GetVal_AsFloat()
-{
- std::string val;
- float tvalf;
-
- if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. No data, seems file is corrupt.");
- if(mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsFloat. Invalid type of XML element, seems file is corrupt.");
-
- ParseHelper_FixTruncatedFloatString(mReader->getNodeData(), val);
- fast_atoreal_move(val.c_str(), tvalf, false);
-
- return tvalf;
-}
-
-uint32_t AMFImporter::XML_ReadNode_GetVal_AsU32()
-{
- if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. No data, seems file is corrupt.");
- if(mReader->getNodeType() != irr::io::EXN_TEXT) throw DeadlyImportError("XML_ReadNode_GetVal_AsU32. Invalid type of XML element, seems file is corrupt.");
-
- return strtoul10(mReader->getNodeData());
-}
-
-void AMFImporter::XML_ReadNode_GetVal_AsString(std::string& pValue)
-{
- if(!mReader->read()) throw DeadlyImportError("XML_ReadNode_GetVal_AsString. No data, seems file is corrupt.");
- if(mReader->getNodeType() != irr::io::EXN_TEXT)
- throw DeadlyImportError("XML_ReadNode_GetVal_AsString. Invalid type of XML element, seems file is corrupt.");
-
- pValue = mReader->getNodeData();
-}
-
-/*********************************************************************************************************************************************/
-/************************************************************ Functions: parse set ***********************************************************/
-/*********************************************************************************************************************************************/
-
-void AMFImporter::ParseHelper_Node_Enter(CAMFImporter_NodeElement* pNode)
-{
- mNodeElement_Cur->Child.push_back(pNode);// add new element to current element child list.
- mNodeElement_Cur = pNode;// switch current element to new one.
-}
-
-void AMFImporter::ParseHelper_Node_Exit()
-{
- // check if we can walk up.
- if(mNodeElement_Cur != nullptr) mNodeElement_Cur = mNodeElement_Cur->Parent;
-}
-
-void AMFImporter::ParseHelper_FixTruncatedFloatString(const char* pInStr, std::string& pOutString)
-{
- size_t instr_len;
-
- pOutString.clear();
- instr_len = strlen(pInStr);
- if(!instr_len) return;
-
- pOutString.reserve(instr_len * 3 / 2);
- // check and correct floats in format ".x". Must be "x.y".
- if(pInStr[0] == '.') pOutString.push_back('0');
-
- pOutString.push_back(pInStr[0]);
- for(size_t ci = 1; ci < instr_len; ci++)
- {
- if((pInStr[ci] == '.') && ((pInStr[ci - 1] == ' ') || (pInStr[ci - 1] == '-') || (pInStr[ci - 1] == '+') || (pInStr[ci - 1] == '\t')))
- {
- pOutString.push_back('0');
- pOutString.push_back('.');
- }
- else
- {
- pOutString.push_back(pInStr[ci]);
- }
- }
-}
-
-static bool ParseHelper_Decode_Base64_IsBase64(const char pChar)
-{
- return (isalnum(pChar) || (pChar == '+') || (pChar == '/'));
-}
-
-void AMFImporter::ParseHelper_Decode_Base64(const std::string& pInputBase64, std::vector& pOutputData) const
-{
- // With help from
- // René Nyffenegger http://www.adp-gmbh.ch/cpp/common/base64.html
- const std::string base64_chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
- uint8_t tidx = 0;
- uint8_t arr4[4], arr3[3];
-
- // check input data
- if(pInputBase64.size() % 4) throw DeadlyImportError("Base64-encoded data must have size multiply of four.");
- // prepare output place
- pOutputData.clear();
- pOutputData.reserve(pInputBase64.size() / 4 * 3);
-
- for(size_t in_len = pInputBase64.size(), in_idx = 0; (in_len > 0) && (pInputBase64[in_idx] != '='); in_len--)
- {
- if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx]))
- {
- arr4[tidx++] = pInputBase64[in_idx++];
- if(tidx == 4)
- {
- for(tidx = 0; tidx < 4; tidx++) arr4[tidx] = (uint8_t)base64_chars.find(arr4[tidx]);
-
- arr3[0] = (arr4[0] << 2) + ((arr4[1] & 0x30) >> 4);
- arr3[1] = ((arr4[1] & 0x0F) << 4) + ((arr4[2] & 0x3C) >> 2);
- arr3[2] = ((arr4[2] & 0x03) << 6) + arr4[3];
- for(tidx = 0; tidx < 3; tidx++) pOutputData.push_back(arr3[tidx]);
-
- tidx = 0;
- }// if(tidx == 4)
- }// if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx]))
- else
- {
- in_idx++;
- }// if(ParseHelper_Decode_Base64_IsBase64(pInputBase64[in_idx])) else
- }
-
- if(tidx)
- {
- for(uint8_t i = tidx; i < 4; i++) arr4[i] = 0;
- for(uint8_t i = 0; i < 4; i++) arr4[i] = (uint8_t)(base64_chars.find(arr4[i]));
-
- arr3[0] = (arr4[0] << 2) + ((arr4[1] & 0x30) >> 4);
- arr3[1] = ((arr4[1] & 0x0F) << 4) + ((arr4[2] & 0x3C) >> 2);
- arr3[2] = ((arr4[2] & 0x03) << 6) + arr4[3];
- for(uint8_t i = 0; i < (tidx - 1); i++) pOutputData.push_back(arr3[i]);
- }
-}
-
-void AMFImporter::ParseFile(const std::string& pFile, IOSystem* pIOHandler)
-{
- irr::io::IrrXMLReader* OldReader = mReader;// store current XMLreader.
- std::unique_ptr file(pIOHandler->Open(pFile, "rb"));
-
- // Check whether we can read from the file
- if(file.get() == NULL) throw DeadlyImportError("Failed to open AMF file " + pFile + ".");
-
- // generate a XML reader for it
- std::unique_ptr mIOWrapper(new CIrrXML_IOStreamReader(file.get()));
- mReader = irr::io::createIrrXMLReader(mIOWrapper.get());
- if(!mReader) throw DeadlyImportError("Failed to create XML reader for file" + pFile + ".");
- //
- // start reading
- // search for root tag
- if(XML_SearchNode("amf"))
- ParseNode_Root();
- else
- throw DeadlyImportError("Root node \"amf\" not found.");
-
- delete mReader;
- // restore old XMLreader
- mReader = OldReader;
-}
-
-//
-//
-// Root XML element.
-// Multi elements - No.
-void AMFImporter::ParseNode_Root()
-{
- std::string unit, version;
- CAMFImporter_NodeElement *ne( nullptr );
-
- // Read attributes for node .
- MACRO_ATTRREAD_LOOPBEG;
- MACRO_ATTRREAD_CHECK_RET("unit", unit, mReader->getAttributeValue);
- MACRO_ATTRREAD_CHECK_RET("version", version, mReader->getAttributeValue);
- MACRO_ATTRREAD_LOOPEND_WSKIP;
-
- // Check attributes
- if(!mUnit.empty())
- {
- if((mUnit != "inch") && (mUnit != "millimeter") && (mUnit != "meter") && (mUnit != "feet") && (mUnit != "micron")) Throw_IncorrectAttrValue("unit");
- }
-
- // create root node element.
- ne = new CAMFImporter_NodeElement_Root(nullptr);
- mNodeElement_Cur = ne;// set first "current" element
- // and assign attribute's values
- ((CAMFImporter_NodeElement_Root*)ne)->Unit = unit;
- ((CAMFImporter_NodeElement_Root*)ne)->Version = version;
-
- // Check for child nodes
- if(!mReader->isEmptyElement())
- {
- MACRO_NODECHECK_LOOPBEGIN("amf");
- if(XML_CheckNode_NameEqual("object")) { ParseNode_Object(); continue; }
- if(XML_CheckNode_NameEqual("material")) { ParseNode_Material(); continue; }
- if(XML_CheckNode_NameEqual("texture")) { ParseNode_Texture(); continue; }
- if(XML_CheckNode_NameEqual("constellation")) { ParseNode_Constellation(); continue; }
- if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
- MACRO_NODECHECK_LOOPEND("amf");
- mNodeElement_Cur = ne;// force restore "current" element
- }// if(!mReader->isEmptyElement())
-
- mNodeElement_List.push_back(ne);// add to node element list because its a new object in graph.
-}
-
-//
-//
-// A collection of objects or constellations with specific relative locations.
-// Multi elements - Yes.
-// Parent element - .
-void AMFImporter::ParseNode_Constellation()
-{
- std::string id;
- CAMFImporter_NodeElement* ne( nullptr );
-
- // Read attributes for node .
- MACRO_ATTRREAD_LOOPBEG;
- MACRO_ATTRREAD_CHECK_RET("id", id, mReader->getAttributeValue);
- MACRO_ATTRREAD_LOOPEND;
-
- // create and if needed - define new grouping object.
- ne = new CAMFImporter_NodeElement_Constellation(mNodeElement_Cur);
-
- CAMFImporter_NodeElement_Constellation& als = *((CAMFImporter_NodeElement_Constellation*)ne);// alias for convenience
-
- if(!id.empty()) als.ID = id;
- // Check for child nodes
- if(!mReader->isEmptyElement())
- {
- ParseHelper_Node_Enter(ne);
- MACRO_NODECHECK_LOOPBEGIN("constellation");
- if(XML_CheckNode_NameEqual("instance")) { ParseNode_Instance(); continue; }
- if(XML_CheckNode_NameEqual("metadata")) { ParseNode_Metadata(); continue; }
- MACRO_NODECHECK_LOOPEND("constellation");
- ParseHelper_Node_Exit();
- }// if(!mReader->isEmptyElement())
- else
- {
- mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
- }// if(!mReader->isEmptyElement()) else
-
- mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
-}
-
-//
-//
-// A collection of objects or constellations with specific relative locations.
-// Multi elements - Yes.
-// Parent element - .
-void AMFImporter::ParseNode_Instance()
-{
- std::string objectid;
- CAMFImporter_NodeElement* ne( nullptr );
-
- // Read attributes for node .
- MACRO_ATTRREAD_LOOPBEG;
- MACRO_ATTRREAD_CHECK_RET("objectid", objectid, mReader->getAttributeValue);
- MACRO_ATTRREAD_LOOPEND;
-
- // used object id must be defined, check that.
- if(objectid.empty()) throw DeadlyImportError("\"objectid\" in must be defined.");
- // create and define new grouping object.
- ne = new CAMFImporter_NodeElement_Instance(mNodeElement_Cur);
-
- CAMFImporter_NodeElement_Instance& als = *((CAMFImporter_NodeElement_Instance*)ne);// alias for convenience
-
- als.ObjectID = objectid;
- // Check for child nodes
- if(!mReader->isEmptyElement())
- {
- bool read_flag[6] = { false, false, false, false, false, false };
-
- als.Delta.Set(0, 0, 0);
- als.Rotation.Set(0, 0, 0);
- ParseHelper_Node_Enter(ne);
- MACRO_NODECHECK_LOOPBEGIN("instance");
- MACRO_NODECHECK_READCOMP_F("deltax", read_flag[0], als.Delta.x);
- MACRO_NODECHECK_READCOMP_F("deltay", read_flag[1], als.Delta.y);
- MACRO_NODECHECK_READCOMP_F("deltaz", read_flag[2], als.Delta.z);
- MACRO_NODECHECK_READCOMP_F("rx", read_flag[3], als.Rotation.x);
- MACRO_NODECHECK_READCOMP_F("ry", read_flag[4], als.Rotation.y);
- MACRO_NODECHECK_READCOMP_F("rz", read_flag[5], als.Rotation.z);
- MACRO_NODECHECK_LOOPEND("instance");
- ParseHelper_Node_Exit();
- // also convert degrees to radians.
- als.Rotation.x = AI_MATH_PI_F * als.Rotation.x / 180.0f;
- als.Rotation.y = AI_MATH_PI_F * als.Rotation.y / 180.0f;
- als.Rotation.z = AI_MATH_PI_F * als.Rotation.z / 180.0f;
- }// if(!mReader->isEmptyElement())
- else
- {
- mNodeElement_Cur->Child.push_back(ne);// Add element to child list of current element
- }// if(!mReader->isEmptyElement()) else
-
- mNodeElement_List.push_back(ne);// and to node element list because its a new object in graph.
-}
-
-//
-// An object definition.
-// Multi elements - Yes.
-// Parent element - .
-void AMFImporter::ParseNode_Object()
-{
- std::string id;
- CAMFImporter_NodeElement* ne( nullptr );
-
- // Read attributes for node