Merge branch 'master' into kimkulling/fix_invalid_delete_issue-5307

kimkulling/fix_invalid_delete_issue-5307
Kim Kulling 2023-11-14 21:59:46 +01:00 committed by GitHub
commit 3c18be8747
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
101 changed files with 1466 additions and 1365 deletions

View File

@ -6,20 +6,14 @@ Open Asset Import Library is a library to load various 3d file formats into a sh
### Current project status ### ### Current project status ###
[![Financial Contributors on Open Collective](https://opencollective.com/assimp/all/badge.svg?label=financial+contributors)](https://opencollective.com/assimp) [![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) ![C/C++ CI](https://github.com/assimp/assimp/workflows/C/C++%20CI/badge.svg)
<a href="https://scan.coverity.com/projects/5607">
<img alt="Coverity Scan Build Status"
src="https://scan.coverity.com/projects/5607/badge.svg"/>
</a>
[![Codacy Badge](https://app.codacy.com/project/badge/Grade/9973693b7bdd4543b07084d5d9cf4745)](https://www.codacy.com/gh/assimp/assimp/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=assimp/assimp&amp;utm_campaign=Badge_Grade) [![Codacy Badge](https://app.codacy.com/project/badge/Grade/9973693b7bdd4543b07084d5d9cf4745)](https://www.codacy.com/gh/assimp/assimp/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=assimp/assimp&amp;utm_campaign=Badge_Grade)
[![Coverage Status](https://coveralls.io/repos/github/assimp/assimp/badge.svg?branch=master)](https://coveralls.io/github/assimp/assimp?branch=master)
[![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Join the chat at https://gitter.im/assimp/assimp](https://badges.gitter.im/assimp/assimp.svg)](https://gitter.im/assimp/assimp?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue") [![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Average time to resolve an issue")
[![Percentage of issues still open](http://isitmaintained.com/badge/open/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Percentage of issues still open") [![Percentage of issues still open](http://isitmaintained.com/badge/open/assimp/assimp.svg)](http://isitmaintained.com/project/assimp/assimp "Percentage of issues still open")
<br> <br>
APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS. APIs are provided for C and C++. There are various bindings to other languages (C#, Java, Python, Delphi, D). Assimp also runs on Android and iOS.
Additionally, assimp features various __mesh post processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more. Additionally, assimp features various __mesh post-processing tools__: normals and tangent space generation, triangulation, vertex cache locality optimization, removal of degenerate primitives and duplicate vertices, sorting by primitive type, merging of redundant materials and many more.
### Latest Doc's ### ### Latest Doc's ###
Please check the latest documents at [Asset-Importer-Lib-Doc](https://assimp-docs.readthedocs.io/en/latest/). Please check the latest documents at [Asset-Importer-Lib-Doc](https://assimp-docs.readthedocs.io/en/latest/).
@ -58,20 +52,21 @@ Take a look into the https://github.com/assimp/assimp/blob/master/Build.md file.
### Other tools ### ### Other tools ###
[open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities. [open3mod](https://github.com/acgessler/open3mod) is a powerful 3D model viewer based on Assimp's import and export abilities.
[Assimp-Viewer(]https://github.com/assimp/assimp_view) is an experimental implementation for an Asset-Viewer based on ImGUI and Assimp (experimental).
#### Repository structure #### #### Repository structure ####
Open Asset Import Library is implemented in C++. The directory structure looks like: Open Asset Import Library is implemented in C++. The directory structure looks like this:
/code Source code /code Source code
/contrib Third-party libraries /contrib Third-party libraries
/doc Documentation (doxysource and pre-compiled docs) /doc Documentation (doxysource and pre-compiled docs)
/fuzz Contains the test-code for the Google-Fuzzer project /fuzz Contains the test code for the Google Fuzzer project
/include Public header C and C++ header files /include Public header C and C++ header files
/scripts Scripts used to generate the loading code for some formats /scripts Scripts are used to generate the loading code for some formats
/port Ports to other languages and scripts to maintain those. /port Ports to other languages and scripts to maintain those.
/test Unit- and regression tests, test suite of models /test Unit- and regression tests, test suite of models
/tools Tools (old assimp viewer, command line `assimp`) /tools Tools (old assimp viewer, command line `assimp`)
/samples A small number of samples to illustrate possible use-cases for Assimp /samples A small number of samples to illustrate possible use cases for Assimp
The source code is organized in the following way: The source code is organized in the following way:
@ -79,9 +74,9 @@ The source code is organized in the following way:
code/CApi Special implementations which are only used for the C-API code/CApi Special implementations which are only used for the C-API
code/Geometry A collection of geometry tools code/Geometry A collection of geometry tools
code/Material The material system code/Material The material system
code/PBR An exporter for physical based models code/PBR An exporter for physical-based models
code/PostProcessing The post-processing steps code/PostProcessing The post-processing steps
code/AssetLib/<FormatName> Implementation for import and export for the format code/AssetLib/<FormatName> Implementation for import and export of the format
### Contributing ### ### Contributing ###
Contributions to assimp are highly appreciated. The easiest way to get involved is to submit Contributions to assimp are highly appreciated. The easiest way to get involved is to submit
@ -118,4 +113,4 @@ and don't sue us if our code doesn't work. Note that, unlike LGPLed code, you ma
For the legal details, see the `LICENSE` file. For the legal details, see the `LICENSE` file.
### Why this name ### ### Why this name ###
Sorry, we're germans :-), no english native speakers ... Sorry, we're germans :-), no English native speakers ...

View File

@ -52,9 +52,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cctype> #include <cctype>
#include <memory> #include <memory>
using namespace Assimp; namespace Assimp {
static const unsigned int NotSet = 0xcdcdcdcd; static constexpr unsigned int NotSet = 0xcdcdcdcd;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Setup final material indices, generae a default material if necessary // Setup final material indices, generae a default material if necessary
@ -68,7 +68,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
unsigned int idx(NotSet); unsigned int idx(NotSet);
for (unsigned int i = 0; i < mScene->mMaterials.size(); ++i) { for (unsigned int i = 0; i < mScene->mMaterials.size(); ++i) {
std::string s = mScene->mMaterials[i].mName; std::string s = mScene->mMaterials[i].mName;
for (char & it : s) { for (char &it : s) {
it = static_cast<char>(::tolower(static_cast<unsigned char>(it))); it = static_cast<char>(::tolower(static_cast<unsigned char>(it)));
} }
@ -262,7 +262,7 @@ void Discreet3DSImporter::ConvertMaterial(D3DS::Material &oldMat,
unsigned int iWire = 1; unsigned int iWire = 1;
mat.AddProperty<int>((int *)&iWire, 1, AI_MATKEY_ENABLE_WIREFRAME); mat.AddProperty<int>((int *)&iWire, 1, AI_MATKEY_ENABLE_WIREFRAME);
} }
[[fallthrough]]; [[fallthrough]];
case D3DS::Discreet3DS::Gouraud: case D3DS::Discreet3DS::Gouraud:
eShading = aiShadingMode_Gouraud; eShading = aiShadingMode_Gouraud;
@ -805,4 +805,6 @@ void Discreet3DSImporter::ConvertScene(aiScene *pcOut) {
} }
} }
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER #endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team Copyright (c) 2006-2022, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -57,8 +56,7 @@ struct aiNode;
struct aiMaterial; struct aiMaterial;
struct aiMesh; struct aiMesh;
namespace Assimp namespace Assimp {
{
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
/** /**
@ -88,7 +86,7 @@ private:
std::map<const aiNode*, aiMatrix4x4> trafos; std::map<const aiNode*, aiMatrix4x4> trafos;
typedef std::multimap<const aiNode*, unsigned int> MeshesByNodeMap; using MeshesByNodeMap = std::multimap<const aiNode*, unsigned int>;
MeshesByNodeMap meshes; MeshesByNodeMap meshes;
}; };

View File

@ -54,9 +54,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
using namespace Assimp; namespace Assimp {
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Discreet 3DS Importer", "Discreet 3DS Importer",
"", "",
"", "",
@ -103,10 +103,6 @@ Discreet3DSImporter::Discreet3DSImporter() :
// empty // empty
} }
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
Discreet3DSImporter::~Discreet3DSImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool Discreet3DSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { bool Discreet3DSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
@ -1339,4 +1335,6 @@ void Discreet3DSImporter::ParseColorChunk(aiColor3D *out, bool acceptPercent) {
(void)bGamma; (void)bGamma;
} }
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER #endif // !! ASSIMP_BUILD_NO_3DS_IMPORTER

View File

@ -59,7 +59,6 @@ struct aiNode;
namespace Assimp { namespace Assimp {
using namespace D3DS; using namespace D3DS;
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
@ -68,7 +67,7 @@ using namespace D3DS;
class Discreet3DSImporter : public BaseImporter { class Discreet3DSImporter : public BaseImporter {
public: public:
Discreet3DSImporter(); Discreet3DSImporter();
~Discreet3DSImporter() override; ~Discreet3DSImporter() override = default;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.

View File

@ -68,7 +68,7 @@ namespace Assimp {
using namespace D3MF; using namespace D3MF;
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"3mf Importer", "3mf Importer",
"", "",
"", "",
@ -81,10 +81,6 @@ static const aiImporterDesc desc = {
"3mf" "3mf"
}; };
D3MFImporter::D3MFImporter() = default;
D3MFImporter::~D3MFImporter() = default;
bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool /*checkSig*/) const { bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool /*checkSig*/) const {
if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) { if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) {
return false; return false;

View File

@ -56,10 +56,10 @@ namespace Assimp {
class D3MFImporter : public BaseImporter { class D3MFImporter : public BaseImporter {
public: public:
/// @brief The default class constructor. /// @brief The default class constructor.
D3MFImporter(); D3MFImporter() = default;
/// @brief The class destructor. /// @brief The class destructor.
~D3MFImporter() override; ~D3MFImporter() override = default;
/// @brief Performs the data format detection. /// @brief Performs the data format detection.
/// @param pFile The filename to check. /// @param pFile The filename to check.

View File

@ -68,7 +68,7 @@ using OpcPackageRelationshipPtr = std::shared_ptr<OpcPackageRelationship>;
class OpcPackageRelationshipReader { class OpcPackageRelationshipReader {
public: public:
OpcPackageRelationshipReader(XmlParser &parser) : OpcPackageRelationshipReader(XmlParser &parser) :
m_relationShips() { mRelations() {
XmlNode root = parser.getRootNode(); XmlNode root = parser.getRootNode();
ParseRootNode(root); ParseRootNode(root);
} }
@ -108,13 +108,13 @@ public:
relPtr->type = currentNode.attribute(XmlTag::RELS_ATTRIB_TYPE).as_string(); relPtr->type = currentNode.attribute(XmlTag::RELS_ATTRIB_TYPE).as_string();
relPtr->target = currentNode.attribute(XmlTag::RELS_ATTRIB_TARGET).as_string(); relPtr->target = currentNode.attribute(XmlTag::RELS_ATTRIB_TARGET).as_string();
if (validateRels(relPtr)) { if (validateRels(relPtr)) {
m_relationShips.push_back(relPtr); mRelations.push_back(relPtr);
} }
} }
} }
} }
std::vector<OpcPackageRelationshipPtr> m_relationShips; std::vector<OpcPackageRelationshipPtr> mRelations;
}; };
static bool IsEmbeddedTexture( const std::string &filename ) { static bool IsEmbeddedTexture( const std::string &filename ) {
@ -214,11 +214,11 @@ std::string D3MFOpcPackage::ReadPackageRootRelationship(IOStream *stream) {
OpcPackageRelationshipReader reader(xmlParser); OpcPackageRelationshipReader reader(xmlParser);
auto itr = std::find_if(reader.m_relationShips.begin(), reader.m_relationShips.end(), [](const OpcPackageRelationshipPtr &rel) { auto itr = std::find_if(reader.mRelations.begin(), reader.mRelations.end(), [](const OpcPackageRelationshipPtr &rel) {
return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE; return rel->type == XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE;
}); });
if (itr == reader.m_relationShips.end()) { if (itr == reader.mRelations.end()) {
throw DeadlyImportError("Cannot find ", XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE); throw DeadlyImportError("Cannot find ", XmlTag::PACKAGE_START_PART_RELATIONSHIP_TYPE);
} }

View File

@ -49,12 +49,12 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
namespace D3MF { namespace D3MF {
static const int IdNotSet = -1; static constexpr int IdNotSet = -1;
namespace { namespace {
static const size_t ColRGBA_Len = 9; static constexpr size_t ColRGBA_Len = 9;
static const size_t ColRGB_Len = 7; static constexpr size_t ColRGB_Len = 7;
// format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1) // format of the color string: #RRGGBBAA or #RRGGBB (3MF Core chapter 5.1.1)
bool validateColorString(const char *color) { bool validateColorString(const char *color) {

View File

@ -60,9 +60,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/Importer.hpp> #include <assimp/Importer.hpp>
#include <memory> #include <memory>
using namespace Assimp; namespace Assimp {
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"AC3D Importer", "AC3D Importer",
"", "",
"", "",
@ -862,4 +862,6 @@ void AC3DImporter::InternReadFile(const std::string &pFile,
} }
} }
} // namespace Assimp
#endif //!defined ASSIMP_BUILD_NO_AC_IMPORTER #endif //!defined ASSIMP_BUILD_NO_AC_IMPORTER

View File

@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
const aiImporterDesc AMFImporter::Description = { static constexpr aiImporterDesc Description = {
"Additive manufacturing file format(AMF) Importer", "Additive manufacturing file format(AMF) Importer",
"smalcom", "smalcom",
"", "",

View File

@ -98,8 +98,12 @@ namespace Assimp {
/// old - <map> and children <u1>, <u2>, <u3>, <v1>, <v2>, <v3> /// old - <map> and children <u1>, <u2>, <u3>, <v1>, <v2>, <v3>
/// ///
class AMFImporter : public BaseImporter { class AMFImporter : public BaseImporter {
private: using AMFMetaDataArray = std::vector<AMFMetadata *>;
struct SPP_Material; // forward declaration using MeshArray = std::vector<aiMesh *>;
using NodeArray = std::vector<aiNode *>;
public:
struct SPP_Material;
/// Data type for post-processing step. More suitable container for part of material's composition. /// Data type for post-processing step. More suitable container for part of material's composition.
struct SPP_Composite { struct SPP_Composite {
@ -107,22 +111,6 @@ private:
std::string Formula; ///< Formula for calculating ratio of \ref Material. std::string Formula; ///< Formula for calculating ratio of \ref Material.
}; };
/// \struct SPP_Material
/// Data type for post-processing step. More suitable container for material.
struct SPP_Material {
std::string ID; ///< Material ID.
std::list<AMFMetadata *> Metadata; ///< Metadata of material.
AMFColor *Color; ///< Color of material.
std::list<SPP_Composite> Composition; ///< List of child materials if current material is composition of few another.
/// Return color calculated for specified coordinate.
/// \param [in] pX - "x" coordinate.
/// \param [in] pY - "y" coordinate.
/// \param [in] pZ - "z" coordinate.
/// \return calculated color.
aiColor4D GetColor(const float pX, const float pY, const float pZ) const;
};
/// Data type for post-processing step. More suitable container for texture. /// Data type for post-processing step. More suitable container for texture.
struct SPP_Texture { struct SPP_Texture {
std::string ID; std::string ID;
@ -139,10 +127,52 @@ private:
const AMFTexMap *TexMap; ///< Face texture mapping data. Equal to nullptr if texture mapping is not set for the face. const AMFTexMap *TexMap; ///< Face texture mapping data. Equal to nullptr if texture mapping is not set for the face.
}; };
using AMFMetaDataArray = std::vector<AMFMetadata*>; /// Data type for post-processing step. More suitable container for material.
using MeshArray = std::vector<aiMesh*>; struct SPP_Material {
using NodeArray = std::vector<aiNode*>; std::string ID; ///< Material ID.
std::list<AMFMetadata *> Metadata; ///< Metadata of material.
AMFColor *Color; ///< Color of material.
std::list<SPP_Composite> Composition; ///< List of child materials if current material is composition of few another.
/// Return color calculated for specified coordinate.
/// \param [in] pX - "x" coordinate.
/// \param [in] pY - "y" coordinate.
/// \param [in] pZ - "z" coordinate.
/// \return calculated color.
aiColor4D GetColor(const float pX, const float pY, const float pZ) const;
};
/// Default constructor.
AMFImporter() AI_NO_EXCEPT;
/// Default destructor.
~AMFImporter() override;
/// Parse AMF file and fill scene graph. The function has no return value. Result can be found by analyzing the generated graph.
/// Also exception can be thrown if trouble will found.
/// \param [in] pFile - name of file to be parsed.
/// \param [in] pIOHandler - pointer to IO helper object.
void ParseFile(const std::string &pFile, IOSystem *pIOHandler);
void ParseHelper_Node_Enter(AMFNodeElementBase *child);
void ParseHelper_Node_Exit();
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const override;
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
const aiImporterDesc *GetInfo() const override;
bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const;
bool Find_ConvertedNode(const std::string &pID, NodeArray &nodeArray, aiNode **pNode) const;
bool Find_ConvertedMaterial(const std::string &pID, const SPP_Material **pConvertedMaterial) const;
AI_WONT_RETURN void Throw_CloseNotFound(const std::string &nodeName) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Throw_IncorrectAttr(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Throw_ID_NotFound(const std::string &pID) const AI_WONT_RETURN_SUFFIX;
void XML_CheckNode_MustHaveChildren(pugi::xml_node &node);
bool XML_SearchNode(const std::string &nodeName);
void ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString);
AMFImporter(const AMFImporter &pScene) = delete;
AMFImporter &operator=(const AMFImporter &pScene) = delete;
private:
/// Clear all temporary data. /// Clear all temporary data.
void Clear(); void Clear();
@ -262,40 +292,9 @@ private:
/// \param [in] pUseOldName - if true then use old name of node(and children) - <map>, instead of new name - <texmap>. /// \param [in] pUseOldName - if true then use old name of node(and children) - <map>, instead of new name - <texmap>.
void ParseNode_TexMap(XmlNode &node, const bool pUseOldName = false); void ParseNode_TexMap(XmlNode &node, const bool pUseOldName = false);
public:
/// Default constructor.
AMFImporter() AI_NO_EXCEPT;
/// Default destructor.
~AMFImporter() override;
/// Parse AMF file and fill scene graph. The function has no return value. Result can be found by analyzing the generated graph.
/// Also exception can be thrown if trouble will found.
/// \param [in] pFile - name of file to be parsed.
/// \param [in] pIOHandler - pointer to IO helper object.
void ParseFile(const std::string &pFile, IOSystem *pIOHandler);
void ParseHelper_Node_Enter(AMFNodeElementBase *child);
void ParseHelper_Node_Exit();
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const override;
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
const aiImporterDesc *GetInfo() const override;
bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const;
bool Find_ConvertedNode(const std::string &pID, NodeArray &nodeArray, aiNode **pNode) const;
bool Find_ConvertedMaterial(const std::string &pID, const SPP_Material **pConvertedMaterial) const;
AI_WONT_RETURN void Throw_CloseNotFound(const std::string &nodeName) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Throw_IncorrectAttr(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Throw_IncorrectAttrValue(const std::string &nodeName, const std::string &pAttrName) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Throw_MoreThanOnceDefined(const std::string &nodeName, const std::string &pNodeType, const std::string &pDescription) AI_WONT_RETURN_SUFFIX;
AI_WONT_RETURN void Throw_ID_NotFound(const std::string &pID) const AI_WONT_RETURN_SUFFIX;
void XML_CheckNode_MustHaveChildren(pugi::xml_node &node);
bool XML_SearchNode(const std::string &nodeName);
void ParseHelper_FixTruncatedFloatString(const char *pInStr, std::string &pOutString);
AMFImporter(const AMFImporter &pScene) = delete;
AMFImporter &operator=(const AMFImporter &pScene) = delete;
private: private:
static const aiImporterDesc Description;
AMFNodeElementBase *mNodeElement_Cur; ///< Current element. AMFNodeElementBase *mNodeElement_Cur; ///< Current element.
std::list<AMFNodeElementBase *> mNodeElement_List; ///< All elements of scene graph. std::list<AMFNodeElementBase *> mNodeElement_List; ///< All elements of scene graph.
XmlParser *mXmlParser; XmlParser *mXmlParser;

View File

@ -63,10 +63,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// utilities // utilities
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
using namespace Assimp; namespace Assimp {
using namespace Assimp::ASE; using namespace Assimp::ASE;
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"ASE Importer", "ASE Importer",
"", "",
"", "",
@ -1262,6 +1262,8 @@ bool ASEImporter::GenerateNormals(ASE::Mesh &mesh) {
return false; return false;
} }
}
#endif // ASSIMP_BUILD_NO_3DS_IMPORTER #endif // ASSIMP_BUILD_NO_3DS_IMPORTER
#endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER #endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER

View File

@ -53,7 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
using namespace Assimp; namespace Assimp {
using namespace Assimp::ASE; using namespace Assimp::ASE;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -1864,6 +1864,8 @@ void Parser::ParseLV4MeshLong(unsigned int &iOut) {
iOut = strtoul10(filePtr, &filePtr); iOut = strtoul10(filePtr, &filePtr);
} }
}
#endif // ASSIMP_BUILD_NO_3DS_IMPORTER #endif // ASSIMP_BUILD_NO_3DS_IMPORTER
#endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER #endif // !! ASSIMP_BUILD_NO_BASE_IMPORTER

View File

@ -65,7 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Assimp Binary Importer", "Assimp Binary Importer",
"Gargaj / Conspiracy", "Gargaj / Conspiracy",
"", "",

View File

@ -59,10 +59,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory> #include <memory>
using namespace Assimp; namespace Assimp {
using namespace std; using namespace std;
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"BlitzBasic 3D Importer", "BlitzBasic 3D Importer",
"", "",
"", "",
@ -79,9 +79,9 @@ static const aiImporterDesc desc = {
#pragma warning(disable : 4018) #pragma warning(disable : 4018)
#endif #endif
//#define DEBUG_B3D // #define DEBUG_B3D
template<typename T> template <typename T>
void DeleteAllBarePointers(std::vector<T> &x) { void DeleteAllBarePointers(std::vector<T> &x) {
for (auto p : x) { for (auto p : x) {
delete p; delete p;
@ -329,7 +329,7 @@ void B3DImporter::ReadBRUS() {
mat->AddProperty(&i, 1, AI_MATKEY_TWOSIDED); mat->AddProperty(&i, 1, AI_MATKEY_TWOSIDED);
} }
//Textures // Textures
for (int i = 0; i < n_texs; ++i) { for (int i = 0; i < n_texs; ++i) {
int texid = ReadInt(); int texid = ReadInt();
if (texid < -1 || (texid >= 0 && texid >= static_cast<int>(_textures.size()))) { if (texid < -1 || (texid >= 0 && texid >= static_cast<int>(_textures.size()))) {
@ -372,7 +372,7 @@ void B3DImporter::ReadVRTS() {
} }
if (_vflags & 2) { if (_vflags & 2) {
ReadQuat(); //skip v 4bytes... ReadQuat(); // skip v 4bytes...
} }
for (int j = 0; j < _tcsets; ++j) { for (int j = 0; j < _tcsets; ++j) {
@ -704,22 +704,22 @@ void B3DImporter::ReadBB3D(aiScene *scene) {
} }
} }
//nodes // nodes
scene->mRootNode = _nodes[0]; scene->mRootNode = _nodes[0];
_nodes.clear(); // node ownership now belongs to scene _nodes.clear(); // node ownership now belongs to scene
//material // material
if (!_materials.size()) { if (!_materials.size()) {
_materials.emplace_back(std::unique_ptr<aiMaterial>(new aiMaterial)); _materials.emplace_back(std::unique_ptr<aiMaterial>(new aiMaterial));
} }
scene->mNumMaterials = static_cast<unsigned int>(_materials.size()); scene->mNumMaterials = static_cast<unsigned int>(_materials.size());
scene->mMaterials = unique_to_array(_materials); scene->mMaterials = unique_to_array(_materials);
//meshes // meshes
scene->mNumMeshes = static_cast<unsigned int>(_meshes.size()); scene->mNumMeshes = static_cast<unsigned int>(_meshes.size());
scene->mMeshes = unique_to_array(_meshes); scene->mMeshes = unique_to_array(_meshes);
//animations // animations
if (_animations.size() == 1 && _nodeAnims.size()) { if (_animations.size() == 1 && _nodeAnims.size()) {
aiAnimation *anim = _animations.back().get(); aiAnimation *anim = _animations.back().get();
@ -738,4 +738,6 @@ void B3DImporter::ReadBB3D(aiScene *scene) {
flip.Execute(scene); flip.Execute(scene);
} }
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_B3D_IMPORTER #endif // !! ASSIMP_BUILD_NO_B3D_IMPORTER

View File

@ -55,10 +55,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <map> #include <map>
#include <memory> #include <memory>
using namespace Assimp; namespace Assimp {
using namespace Assimp::Formatter; using namespace Assimp::Formatter;
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"BVH Importer (MoCap)", "BVH Importer (MoCap)",
"", "",
"", "",
@ -73,8 +74,8 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Aborts the file reading with an exception // Aborts the file reading with an exception
template<typename... T> template <typename... T>
AI_WONT_RETURN void BVHLoader::ThrowException(T&&... args) { AI_WONT_RETURN void BVHLoader::ThrowException(T &&...args) {
throw DeadlyImportError(mFileName, ":", mLine, " - ", args...); throw DeadlyImportError(mFileName, ":", mLine, " - ", args...);
} }
@ -426,7 +427,7 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
nodeAnim->mNodeName.Set(nodeName); nodeAnim->mNodeName.Set(nodeName);
std::map<BVHLoader::ChannelType, int> channelMap; std::map<BVHLoader::ChannelType, int> channelMap;
//Build map of channels // Build map of channels
for (unsigned int channel = 0; channel < node.mChannels.size(); ++channel) { for (unsigned int channel = 0; channel < node.mChannels.size(); ++channel) {
channelMap[node.mChannels[channel]] = channel; channelMap[node.mChannels[channel]] = channel;
} }
@ -441,7 +442,7 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
// Now compute all translations // Now compute all translations
for (BVHLoader::ChannelType channel = Channel_PositionX; channel <= Channel_PositionZ; channel = (BVHLoader::ChannelType)(channel + 1)) { for (BVHLoader::ChannelType channel = Channel_PositionX; channel <= Channel_PositionZ; channel = (BVHLoader::ChannelType)(channel + 1)) {
//Find channel in node // Find channel in node
std::map<BVHLoader::ChannelType, int>::iterator mapIter = channelMap.find(channel); std::map<BVHLoader::ChannelType, int>::iterator mapIter = channelMap.find(channel);
if (mapIter == channelMap.end()) if (mapIter == channelMap.end())
@ -485,30 +486,27 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
for (unsigned int fr = 0; fr < mAnimNumFrames; ++fr) { for (unsigned int fr = 0; fr < mAnimNumFrames; ++fr) {
aiMatrix4x4 temp; aiMatrix4x4 temp;
aiMatrix3x3 rotMatrix; aiMatrix3x3 rotMatrix;
for (unsigned int channelIdx = 0; channelIdx < node.mChannels.size(); ++ channelIdx) { for (unsigned int channelIdx = 0; channelIdx < node.mChannels.size(); ++channelIdx) {
switch (node.mChannels[channelIdx]) { switch (node.mChannels[channelIdx]) {
case Channel_RotationX: case Channel_RotationX: {
{
const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f; const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
aiMatrix4x4::RotationX( angle, temp); rotMatrix *= aiMatrix3x3( temp); aiMatrix4x4::RotationX(angle, temp);
} rotMatrix *= aiMatrix3x3(temp);
break; } break;
case Channel_RotationY: case Channel_RotationY: {
{
const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f; const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
aiMatrix4x4::RotationY( angle, temp); rotMatrix *= aiMatrix3x3( temp); aiMatrix4x4::RotationY(angle, temp);
} rotMatrix *= aiMatrix3x3(temp);
break; } break;
case Channel_RotationZ: case Channel_RotationZ: {
{
const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f; const float angle = node.mChannelValues[fr * node.mChannels.size() + channelIdx] * float(AI_MATH_PI) / 180.0f;
aiMatrix4x4::RotationZ( angle, temp); rotMatrix *= aiMatrix3x3( temp); aiMatrix4x4::RotationZ(angle, temp);
} rotMatrix *= aiMatrix3x3(temp);
break; } break;
default: default:
break; break;
} }
} }
rotkey->mTime = double(fr); rotkey->mTime = double(fr);
rotkey->mValue = aiQuaternion(rotMatrix); rotkey->mValue = aiQuaternion(rotMatrix);
++rotkey; ++rotkey;
@ -525,4 +523,6 @@ void BVHLoader::CreateAnimation(aiScene *pScene) {
} }
} }
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_BVH_IMPORTER #endif // !! ASSIMP_BUILD_NO_BVH_IMPORTER

View File

@ -69,11 +69,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// zlib is needed for compressed blend files // zlib is needed for compressed blend files
#ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND #ifndef ASSIMP_BUILD_NO_COMPRESSED_BLEND
#include "Common/Compression.h" #include "Common/Compression.h"
/* #ifdef ASSIMP_BUILD_NO_OWN_ZLIB
# include <zlib.h>
# else
# include "../contrib/zlib/zlib.h"
# endif*/
#endif #endif
namespace Assimp { namespace Assimp {
@ -89,7 +84,7 @@ using namespace Assimp;
using namespace Assimp::Blender; using namespace Assimp::Blender;
using namespace Assimp::Formatter; using namespace Assimp::Formatter;
static const aiImporterDesc blenderDesc = { static constexpr aiImporterDesc blenderDesc = {
"Blender 3D Importer (http://www.blender3d.org)", "Blender 3D Importer (http://www.blender3d.org)",
"", "",
"", "",

View File

@ -61,11 +61,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory> #include <memory>
using namespace Assimp; namespace Assimp {
using namespace Assimp::COB; using namespace Assimp::COB;
using namespace Assimp::Formatter; using namespace Assimp::Formatter;
static const float units[] = { static constexpr float units[] = {
1000.f, 1000.f,
100.f, 100.f,
1.f, 1.f,
@ -76,7 +76,7 @@ static const float units[] = {
1.f / 1609.344f 1.f / 1609.344f
}; };
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"TrueSpace Object Importer", "TrueSpace Object Importer",
"", "",
"", "",
@ -89,14 +89,6 @@ static const aiImporterDesc desc = {
"cob scn" "cob scn"
}; };
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
COBImporter::COBImporter() = default;
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
COBImporter::~COBImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool COBImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { bool COBImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
@ -1172,4 +1164,6 @@ void COBImporter::ReadUnit_Binary(COB::Scene &out, StreamReaderLE &reader, const
ASSIMP_LOG_WARN("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist"); ASSIMP_LOG_WARN("`Unit` chunk ", nfo.id, " is a child of ", nfo.parent_id, " which does not exist");
} }
}
#endif // ASSIMP_BUILD_NO_COB_IMPORTER #endif // ASSIMP_BUILD_NO_COB_IMPORTER

View File

@ -56,16 +56,16 @@ class LineSplitter;
// TinyFormatter.h // TinyFormatter.h
namespace Formatter { namespace Formatter {
template <typename T, typename TR, typename A> template <typename T, typename TR, typename A>
class basic_formatter; class basic_formatter;
typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>> format; typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>> format;
} // namespace Formatter } // namespace Formatter
// COBScene.h // COBScene.h
namespace COB { namespace COB {
struct ChunkInfo; struct ChunkInfo;
struct Node; struct Node;
struct Scene; struct Scene;
} // namespace COB } // namespace COB
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
@ -75,8 +75,8 @@ struct Scene;
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
class COBImporter : public BaseImporter { class COBImporter : public BaseImporter {
public: public:
COBImporter(); COBImporter() = default;
~COBImporter() override; ~COBImporter() override = default;
// -------------------- // --------------------
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool CanRead(const std::string &pFile, IOSystem *pIOHandler,

View File

@ -44,9 +44,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
/** @file CSMLoader.cpp /** @file CSMLoader.cpp
* Implementation of the CSM importer class. * Implementation of the CSM importer class.
*/ */
#ifndef ASSIMP_BUILD_NO_CSM_IMPORTER #ifndef ASSIMP_BUILD_NO_CSM_IMPORTER
#include "CSMLoader.h" #include "CSMLoader.h"
@ -63,7 +60,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"CharacterStudio Motion Importer (MoCap)", "CharacterStudio Motion Importer (MoCap)",
"", "",
"", "",
@ -79,13 +76,9 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
CSMImporter::CSMImporter() CSMImporter::CSMImporter() : noSkeletonMesh(){
: noSkeletonMesh() // empty
{} }
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
CSMImporter::~CSMImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.

View File

@ -61,7 +61,7 @@ namespace Assimp {
class CSMImporter : public BaseImporter { class CSMImporter : public BaseImporter {
public: public:
CSMImporter(); CSMImporter();
~CSMImporter() override; ~CSMImporter() override = default;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
@ -81,9 +81,8 @@ protected:
private: private:
bool noSkeletonMesh; bool noSkeletonMesh;
}; // end of class CSMImporter };
} // end of namespace Assimp } // namespace Assimp
#endif // AI_AC3DIMPORTER_H_INC #endif // AI_AC3DIMPORTER_H_INC

View File

@ -64,7 +64,7 @@ namespace Assimp {
using namespace Assimp::Formatter; using namespace Assimp::Formatter;
using namespace Assimp::Collada; using namespace Assimp::Collada;
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Collada Importer", "Collada Importer",
"", "",
"", "",
@ -101,10 +101,6 @@ ColladaLoader::ColladaLoader() :
// empty // empty
} }
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
ColladaLoader::~ColladaLoader() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {

View File

@ -86,7 +86,7 @@ public:
ColladaLoader(); ColladaLoader();
/// The class destructor. /// The class destructor.
~ColladaLoader() override; ~ColladaLoader() override = default;
/// Returns whether the class can handle the format of the given file. /// Returns whether the class can handle the format of the given file.
/// @see BaseImporter::CanRead() for more details. /// @see BaseImporter::CanRead() for more details.

View File

@ -70,7 +70,7 @@ static const aiColor4D AI_DXF_DEFAULT_COLOR(aiColor4D(0.6f, 0.6f, 0.6f, 0.6f));
// color indices for DXF - 16 are supported, the table is // color indices for DXF - 16 are supported, the table is
// taken directly from the DXF spec. // taken directly from the DXF spec.
static aiColor4D g_aclrDxfIndexColors[] = { static const aiColor4D g_aclrDxfIndexColors[] = {
aiColor4D(0.6f, 0.6f, 0.6f, 1.0f), aiColor4D(0.6f, 0.6f, 0.6f, 1.0f),
aiColor4D (1.0f, 0.0f, 0.0f, 1.0f), // red aiColor4D (1.0f, 0.0f, 0.0f, 1.0f), // red
aiColor4D (0.0f, 1.0f, 0.0f, 1.0f), // green aiColor4D (0.0f, 1.0f, 0.0f, 1.0f), // green
@ -97,7 +97,7 @@ static const int GroupCode_XComp = 10;
static const int GroupCode_YComp = 20; static const int GroupCode_YComp = 20;
static const int GroupCode_ZComp = 30; static const int GroupCode_ZComp = 30;
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Drawing Interchange Format (DXF) Importer", "Drawing Interchange Format (DXF) Importer",
"", "",
"", "",

View File

@ -51,6 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXUtil.h" #include "FBXUtil.h"
#include <assimp/defs.h> #include <assimp/defs.h>
#include <stdint.h> #include <stdint.h>
#include <cstdint>
#include <assimp/Exceptional.h> #include <assimp/Exceptional.h>
#include <assimp/ByteSwapper.h> #include <assimp/ByteSwapper.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>

View File

@ -577,16 +577,17 @@ void FBXConverter::GetRotationMatrix(Model::RotOrder mode, const aiVector3D &rot
bool is_id[3] = { true, true, true }; bool is_id[3] = { true, true, true };
aiMatrix4x4 temp[3]; aiMatrix4x4 temp[3];
if (std::fabs(rotation.z) > angle_epsilon) { const auto rot = AI_DEG_TO_RAD(rotation);
aiMatrix4x4::RotationZ(AI_DEG_TO_RAD(rotation.z), temp[2]); if (std::fabs(rot.z) > angle_epsilon) {
aiMatrix4x4::RotationZ(rot.z, temp[2]);
is_id[2] = false; is_id[2] = false;
} }
if (std::fabs(rotation.y) > angle_epsilon) { if (std::fabs(rot.y) > angle_epsilon) {
aiMatrix4x4::RotationY(AI_DEG_TO_RAD(rotation.y), temp[1]); aiMatrix4x4::RotationY(rot.y, temp[1]);
is_id[1] = false; is_id[1] = false;
} }
if (std::fabs(rotation.x) > angle_epsilon) { if (std::fabs(rot.x) > angle_epsilon) {
aiMatrix4x4::RotationX(AI_DEG_TO_RAD(rotation.x), temp[0]); aiMatrix4x4::RotationX(rot.x, temp[0]);
is_id[0] = false; is_id[0] = false;
} }
@ -3225,7 +3226,6 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
aiVector3D defTranslate = PropertyGet(props, "Lcl Translation", aiVector3D(0.f, 0.f, 0.f)); aiVector3D defTranslate = PropertyGet(props, "Lcl Translation", aiVector3D(0.f, 0.f, 0.f));
aiVector3D defRotation = PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f)); aiVector3D defRotation = PropertyGet(props, "Lcl Rotation", aiVector3D(0.f, 0.f, 0.f));
aiVector3D defScale = PropertyGet(props, "Lcl Scaling", aiVector3D(1.f, 1.f, 1.f)); aiVector3D defScale = PropertyGet(props, "Lcl Scaling", aiVector3D(1.f, 1.f, 1.f));
aiQuaternion defQuat = EulerToQuaternion(defRotation, rotOrder);
aiVectorKey* outTranslations = new aiVectorKey[keyCount]; aiVectorKey* outTranslations = new aiVectorKey[keyCount];
aiQuatKey* outRotations = new aiQuatKey[keyCount]; aiQuatKey* outRotations = new aiQuatKey[keyCount];
@ -3241,8 +3241,9 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
} }
if (keyframeLists[TransformationComp_Rotation].size() > 0) { if (keyframeLists[TransformationComp_Rotation].size() > 0) {
InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], defRotation, maxTime, minTime, rotOrder); InterpolateKeys(outRotations, keytimes, keyframeLists[TransformationComp_Rotation], AI_DEG_TO_RAD(defRotation), maxTime, minTime, rotOrder);
} else { } else {
aiQuaternion defQuat = EulerToQuaternion(AI_DEG_TO_RAD(defRotation), rotOrder);
for (size_t i = 0; i < keyCount; ++i) { for (size_t i = 0; i < keyCount; ++i) {
outRotations[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps; outRotations[i].mTime = CONVERT_FBX_TIME(keytimes[i]) * anim_fps;
outRotations[i].mValue = defQuat; outRotations[i].mValue = defQuat;
@ -3264,7 +3265,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
const aiVector3D& preRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok); const aiVector3D& preRotation = PropertyGet<aiVector3D>(props, "PreRotation", ok);
if (ok && preRotation.SquareLength() > zero_epsilon) { if (ok && preRotation.SquareLength() > zero_epsilon) {
const aiQuaternion preQuat = EulerToQuaternion(preRotation, Model::RotOrder_EulerXYZ); const aiQuaternion preQuat = EulerToQuaternion(AI_DEG_TO_RAD(preRotation), Model::RotOrder_EulerXYZ);
for (size_t i = 0; i < keyCount; ++i) { for (size_t i = 0; i < keyCount; ++i) {
outRotations[i].mValue = preQuat * outRotations[i].mValue; outRotations[i].mValue = preQuat * outRotations[i].mValue;
} }
@ -3272,7 +3273,7 @@ aiNodeAnim* FBXConverter::GenerateSimpleNodeAnim(const std::string& name,
const aiVector3D& postRotation = PropertyGet<aiVector3D>(props, "PostRotation", ok); const aiVector3D& postRotation = PropertyGet<aiVector3D>(props, "PostRotation", ok);
if (ok && postRotation.SquareLength() > zero_epsilon) { if (ok && postRotation.SquareLength() > zero_epsilon) {
const aiQuaternion postQuat = EulerToQuaternion(postRotation, Model::RotOrder_EulerXYZ); const aiQuaternion postQuat = EulerToQuaternion(AI_DEG_TO_RAD(postRotation), Model::RotOrder_EulerXYZ);
for (size_t i = 0; i < keyCount; ++i) { for (size_t i = 0; i < keyCount; ++i) {
outRotations[i].mValue = outRotations[i].mValue * postQuat; outRotations[i].mValue = outRotations[i].mValue * postQuat;
} }

View File

@ -74,8 +74,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// https://code.blender.org/2013/08/fbx-binary-file-format-specification/ // https://code.blender.org/2013/08/fbx-binary-file-format-specification/
// https://wiki.blender.org/index.php/User:Mont29/Foundation/FBX_File_Structure // https://wiki.blender.org/index.php/User:Mont29/Foundation/FBX_File_Structure
const ai_real DEG = ai_real( 57.29577951308232087679815481 ); // degrees per radian
using namespace Assimp; using namespace Assimp;
using namespace Assimp::FBX; using namespace Assimp::FBX;
@ -1391,7 +1389,7 @@ void FBXExporter::WriteObjects ()
aiMaterial* m = mScene->mMaterials[i]; aiMaterial* m = mScene->mMaterials[i];
// these are used to receive material data // these are used to receive material data
float f; aiColor3D c; ai_real f; aiColor3D c;
// start the node record // start the node record
FBX::Node n("Material"); FBX::Node n("Material");
@ -2434,7 +2432,7 @@ void FBXExporter::WriteObjects ()
aiMatrix4x4 m(k.mValue.GetMatrix()); aiMatrix4x4 m(k.mValue.GetMatrix());
aiVector3D qs, qr, qt; aiVector3D qs, qr, qt;
m.Decompose(qs, qr, qt); m.Decompose(qs, qr, qt);
qr *= DEG; qr = AI_RAD_TO_DEG(qr);
xval.push_back(qr.x); xval.push_back(qr.x);
yval.push_back(qr.y); yval.push_back(qr.y);
zval.push_back(qr.z); zval.push_back(qr.z);
@ -2515,9 +2513,10 @@ void FBXExporter::WriteModelNode(
); );
} }
if (r != zero) { if (r != zero) {
r = AI_RAD_TO_DEG(r);
p.AddP70( p.AddP70(
"Lcl Rotation", "Lcl Rotation", "", "A", "Lcl Rotation", "Lcl Rotation", "", "A",
double(DEG*r.x), double(DEG*r.y), double(DEG*r.z) double(r.x), double(r.y), double(r.z)
); );
} }
if (s != one) { if (s != one) {
@ -2601,8 +2600,7 @@ void FBXExporter::WriteModelNodes(
transform_chain.emplace_back(elem->first, t); transform_chain.emplace_back(elem->first, t);
break; break;
case 'r': // rotation case 'r': // rotation
r *= float(DEG); transform_chain.emplace_back(elem->first, AI_RAD_TO_DEG(r));
transform_chain.emplace_back(elem->first, r);
break; break;
case 's': // scale case 's': // scale
transform_chain.emplace_back(elem->first, s); transform_chain.emplace_back(elem->first, s);

View File

@ -72,30 +72,25 @@ using namespace Assimp::Formatter;
using namespace Assimp::FBX; using namespace Assimp::FBX;
namespace { namespace {
static constexpr aiImporterDesc desc = {
static const aiImporterDesc desc = { "Autodesk FBX Importer",
"Autodesk FBX Importer", "",
"", "",
"", "",
"", aiImporterFlags_SupportTextFlavour,
aiImporterFlags_SupportTextFlavour, 0,
0, 0,
0, 0,
0, 0,
0, "fbx"
"fbx" };
};
} }
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by #Importer
FBXImporter::FBXImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool FBXImporter::CanRead(const std::string & pFile, IOSystem * pIOHandler, bool /*checkSig*/) const { bool FBXImporter::CanRead(const std::string & pFile, IOSystem * pIOHandler, bool /*checkSig*/) const {
// at least ASCII-FBX files usually have a 'FBX' somewhere in their head // at least ASCII-FBX files usually have a 'FBX' somewhere in their head
static const char *tokens[] = { "fbx" }; static const char *tokens[] = { " \n\r\n " };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens)); return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
} }

View File

@ -70,7 +70,7 @@ typedef class basic_formatter<char, std::char_traits<char>, std::allocator<char>
class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> { class FBXImporter : public BaseImporter, public LogFunctions<FBXImporter> {
public: public:
/// @brief The class constructor. /// @brief The class constructor.
FBXImporter(); FBXImporter() = default;
/// @brief The class destructor, default implementation. /// @brief The class destructor, default implementation.
~FBXImporter() override = default; ~FBXImporter() override = default;

View File

@ -57,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"3D GameStudio Heightmap (HMP) Importer", "3D GameStudio Heightmap (HMP) Importer",
"", "",
"", "",

View File

@ -103,7 +103,7 @@ void ConvertUnit(const ::Assimp::STEP::EXPRESS::DataType &dt, ConversionData &co
} // namespace } // namespace
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Industry Foundation Classes (IFC) Importer", "Industry Foundation Classes (IFC) Importer",
"", "",
"", "",
@ -185,7 +185,7 @@ void IFCImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
size_t total = 0; size_t total = 0;
int read = 0; int read = 0;
do { do {
int bufferSize = fileInfo.uncompressed_size < INT16_MAX ? fileInfo.uncompressed_size : INT16_MAX; unsigned bufferSize = fileInfo.uncompressed_size < INT16_MAX ? static_cast<unsigned>(fileInfo.uncompressed_size) : INT16_MAX;
void *buffer = malloc(bufferSize); void *buffer = malloc(bufferSize);
read = unzReadCurrentFile(zip, buffer, bufferSize); read = unzReadCurrentFile(zip, buffer, bufferSize);
if (read > 0) { if (read > 0) {

View File

@ -1372,7 +1372,7 @@ std::vector<IfcVector2> GetContourInPlane2D(const std::shared_ptr<TempMesh>& mes
const std::vector<IfcVector3>& va = mesh->mVerts; const std::vector<IfcVector3>& va = mesh->mVerts;
if(va.size() <= 2) { if(va.size() <= 2) {
std::stringstream msg; std::stringstream msg;
msg << "Skipping: Only " << va.size() << " verticies in opening mesh."; msg << "Skipping: Only " << va.size() << " vertices in opening mesh.";
IFCImporter::LogDebug(msg.str().c_str()); IFCImporter::LogDebug(msg.str().c_str());
ok = false; ok = false;
return contour; return contour;

View File

@ -59,7 +59,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// http://sauerbraten.org/iqm/ // http://sauerbraten.org/iqm/
// https://github.com/lsalzman/iqm // https://github.com/lsalzman/iqm
inline void swap_block( uint32_t *block, size_t size ){ inline void swap_block( uint32_t *block, size_t size ){
(void)block; // suppress 'unreferenced formal parameter' MSVC warning (void)block; // suppress 'unreferenced formal parameter' MSVC warning
size >>= 2; size >>= 2;
@ -67,7 +66,7 @@ inline void swap_block( uint32_t *block, size_t size ){
AI_SWAP4( block[ i ] ); AI_SWAP4( block[ i ] );
} }
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Inter-Quake Model Importer", "Inter-Quake Model Importer",
"", "",
"", "",
@ -100,13 +99,6 @@ bool IQMImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c
if (!pIOHandler) { if (!pIOHandler) {
return true; return true;
} }
/*
* don't use CheckMagicToken because that checks with swapped bytes too, leading to false
* positives. This magic is not uint32_t, but char[4], so memcmp is the best way
const char* tokens[] = {"3DMO", "3dmo"};
return CheckMagicToken(pIOHandler,pFile,tokens,2,0,4);
*/
std::unique_ptr<IOStream> pStream(pIOHandler->Open(pFile, "rb")); std::unique_ptr<IOStream> pStream(pIOHandler->Open(pFile, "rb"));
unsigned char data[15]; unsigned char data[15];
if (!pStream || 15 != pStream->Read(data, 1, 15)) { if (!pStream || 15 != pStream->Read(data, 1, 15)) {

View File

@ -66,7 +66,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Irrlicht Scene Reader", "Irrlicht Scene Reader",
"", "",
"", "",
@ -575,8 +575,8 @@ void SetupMapping(aiMaterial *mat, aiTextureMapping mode, const aiVector3D &axis
m->mSemantic = prop->mSemantic; m->mSemantic = prop->mSemantic;
m->mType = aiPTI_Float; m->mType = aiPTI_Float;
m->mDataLength = 12; m->mDataLength = sizeof(aiVector3D);
m->mData = new char[12]; m->mData = new char[m->mDataLength];
*((aiVector3D *)m->mData) = axis; *((aiVector3D *)m->mData) = axis;
p.push_back(m); p.push_back(m);
} }

View File

@ -56,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Irrlicht Mesh Reader", "Irrlicht Mesh Reader",
"", "",
"", "",

View File

@ -51,64 +51,56 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "LWOLoader.h" #include "LWOLoader.h"
using namespace Assimp; using namespace Assimp;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWOBFile() void LWOImporter::LoadLWOBFile() {
{
LE_NCONST uint8_t* const end = mFileBuffer + fileSize; LE_NCONST uint8_t* const end = mFileBuffer + fileSize;
bool running = true; bool running = true;
while (running) while (running) {
{ if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)
if (mFileBuffer + sizeof(IFF::ChunkHeader) > end)break; break;
const IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer); const IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer);
if (mFileBuffer + head.length > end) if (mFileBuffer + head.length > end) {
{
throw DeadlyImportError("LWOB: Invalid chunk length"); throw DeadlyImportError("LWOB: Invalid chunk length");
} }
uint8_t* const next = mFileBuffer+head.length; uint8_t* const next = mFileBuffer+head.length;
switch (head.type) switch (head.type) {
{
// vertex list // vertex list
case AI_LWO_PNTS: case AI_LWO_PNTS: {
{
if (!mCurLayer->mTempPoints.empty()) if (!mCurLayer->mTempPoints.empty())
ASSIMP_LOG_WARN("LWO: PNTS chunk encountered twice"); ASSIMP_LOG_WARN("LWO: PNTS chunk encountered twice");
else LoadLWOPoints(head.length); else
break; LoadLWOPoints(head.length);
} } break;
// face list case AI_LWO_POLS: { // face list
case AI_LWO_POLS: if (!mCurLayer->mFaces.empty())
{ ASSIMP_LOG_WARN("LWO: POLS chunk encountered twice");
else
LoadLWOBPolygons(head.length);
} break;
if (!mCurLayer->mFaces.empty()) case AI_LWO_SRFS: // list of tags
ASSIMP_LOG_WARN("LWO: POLS chunk encountered twice"); {
else LoadLWOBPolygons(head.length); if (!mTags->empty())
break; ASSIMP_LOG_WARN("LWO: SRFS chunk encountered twice");
} else
// list of tags LoadLWOTags(head.length);
case AI_LWO_SRFS: } break;
{
if (!mTags->empty())
ASSIMP_LOG_WARN("LWO: SRFS chunk encountered twice");
else LoadLWOTags(head.length);
break;
}
// surface chunk case AI_LWO_SURF: // surface chunk
case AI_LWO_SURF: {
{ LoadLWOBSurface(head.length);
LoadLWOBSurface(head.length); } break;
default:
break; break;
}
} }
mFileBuffer = next; mFileBuffer = next;
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWOBPolygons(unsigned int length) void LWOImporter::LoadLWOBPolygons(unsigned int length) {
{
// first find out how many faces and vertices we'll finally need // first find out how many faces and vertices we'll finally need
LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length); LE_NCONST uint16_t* const end = (LE_NCONST uint16_t*)(mFileBuffer+length);
LE_NCONST uint16_t* cursor = (LE_NCONST uint16_t*)mFileBuffer; LE_NCONST uint16_t* cursor = (LE_NCONST uint16_t*)mFileBuffer;
@ -123,8 +115,7 @@ void LWOImporter::LoadLWOBPolygons(unsigned int length)
CountVertsAndFacesLWOB(iNumVertices,iNumFaces,cursor,end); CountVertsAndFacesLWOB(iNumVertices,iNumFaces,cursor,end);
// allocate the output array and copy face indices // allocate the output array and copy face indices
if (iNumFaces) if (iNumFaces) {
{
cursor = (LE_NCONST uint16_t*)mFileBuffer; cursor = (LE_NCONST uint16_t*)mFileBuffer;
mCurLayer->mFaces.resize(iNumFaces); mCurLayer->mFaces.resize(iNumFaces);
@ -135,10 +126,8 @@ void LWOImporter::LoadLWOBPolygons(unsigned int length)
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& faces, void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& faces,
LE_NCONST uint16_t*& cursor, const uint16_t* const end, unsigned int max) LE_NCONST uint16_t*& cursor, const uint16_t* const end, unsigned int max) {
{ while (cursor < end && max--) {
while (cursor < end && max--)
{
uint16_t numIndices; uint16_t numIndices;
// must have 2 shorts left for numIndices and surface // must have 2 shorts left for numIndices and surface
if (end - cursor < 2) { if (end - cursor < 2) {
@ -154,8 +143,7 @@ void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& face
cursor += numIndices; cursor += numIndices;
int16_t surface; int16_t surface;
::memcpy(&surface, cursor++, 2); ::memcpy(&surface, cursor++, 2);
if (surface < 0) if (surface < 0) {
{
// there are detail polygons // there are detail polygons
::memcpy(&numIndices, cursor++, 2); ::memcpy(&numIndices, cursor++, 2);
CountVertsAndFacesLWOB(verts,faces,cursor,end,numIndices); CountVertsAndFacesLWOB(verts,faces,cursor,end,numIndices);
@ -167,18 +155,14 @@ void LWOImporter::CountVertsAndFacesLWOB(unsigned int& verts, unsigned int& face
void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it, void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
LE_NCONST uint16_t*& cursor, LE_NCONST uint16_t*& cursor,
const uint16_t* const end, const uint16_t* const end,
unsigned int max) unsigned int max) {
{ while (cursor < end && max--) {
while (cursor < end && max--)
{
LWO::Face& face = *it;++it; LWO::Face& face = *it;++it;
uint16_t numIndices; uint16_t numIndices;
::memcpy(&numIndices, cursor++, 2); ::memcpy(&numIndices, cursor++, 2);
face.mNumIndices = numIndices; face.mNumIndices = numIndices;
if(face.mNumIndices) if(face.mNumIndices) {
{ if (cursor + face.mNumIndices >= end) {
if (cursor + face.mNumIndices >= end)
{
break; break;
} }
face.mIndices = new unsigned int[face.mNumIndices]; face.mIndices = new unsigned int[face.mNumIndices];
@ -187,8 +171,7 @@ void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
uint16_t index; uint16_t index;
::memcpy(&index, cursor++, 2); ::memcpy(&index, cursor++, 2);
mi = index; mi = index;
if (mi > mCurLayer->mTempPoints.size()) if (mi > mCurLayer->mTempPoints.size()) {
{
ASSIMP_LOG_WARN("LWOB: face index is out of range"); ASSIMP_LOG_WARN("LWOB: face index is out of range");
mi = (unsigned int)mCurLayer->mTempPoints.size()-1; mi = (unsigned int)mCurLayer->mTempPoints.size()-1;
} }
@ -198,15 +181,13 @@ void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
} }
int16_t surface; int16_t surface;
::memcpy(&surface, cursor++, 2); ::memcpy(&surface, cursor++, 2);
if (surface < 0) if (surface < 0) {
{
surface = -surface; surface = -surface;
// there are detail polygons. // there are detail polygons.
uint16_t numPolygons; uint16_t numPolygons;
::memcpy(&numPolygons, cursor++, 2); ::memcpy(&numPolygons, cursor++, 2);
if (cursor < end) if (cursor < end) {
{
CopyFaceIndicesLWOB(it,cursor,end,numPolygons); CopyFaceIndicesLWOB(it,cursor,end,numPolygons);
} }
} }
@ -215,8 +196,7 @@ void LWOImporter::CopyFaceIndicesLWOB(FaceList::iterator& it,
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned int size) LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned int size) {
{
list.emplace_back(); list.emplace_back();
LWO::Texture* tex = &list.back(); LWO::Texture* tex = &list.back();
@ -224,8 +204,7 @@ LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned i
GetS0(type,size); GetS0(type,size);
const char* s = type.c_str(); const char* s = type.c_str();
if(strstr(s, "Image Map")) if(strstr(s, "Image Map")) {
{
// Determine mapping type // Determine mapping type
if(strstr(s, "Planar")) if(strstr(s, "Planar"))
tex->mapMode = LWO::Texture::Planar; tex->mapMode = LWO::Texture::Planar;
@ -237,9 +216,7 @@ LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned i
tex->mapMode = LWO::Texture::Cubic; tex->mapMode = LWO::Texture::Cubic;
else if(strstr(s, "Front")) else if(strstr(s, "Front"))
tex->mapMode = LWO::Texture::FrontProjection; tex->mapMode = LWO::Texture::FrontProjection;
} } else {
else
{
// procedural or gradient, not supported // procedural or gradient, not supported
ASSIMP_LOG_ERROR("LWOB: Unsupported legacy texture: ", type); ASSIMP_LOG_ERROR("LWOB: Unsupported legacy texture: ", type);
} }
@ -248,8 +225,7 @@ LWO::Texture* LWOImporter::SetupNewTextureLWOB(LWO::TextureList& list,unsigned i
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void LWOImporter::LoadLWOBSurface(unsigned int size) void LWOImporter::LoadLWOBSurface(unsigned int size) {
{
LE_NCONST uint8_t* const end = mFileBuffer + size; LE_NCONST uint8_t* const end = mFileBuffer + size;
mSurfaces->push_back( LWO::Surface () ); mSurfaces->push_back( LWO::Surface () );
@ -277,148 +253,147 @@ void LWOImporter::LoadLWOBSurface(unsigned int size)
} }
uint8_t* const next = mFileBuffer+head.length; uint8_t* const next = mFileBuffer+head.length;
switch (head.type) switch (head.type) {
{ // diffuse color
// diffuse color case AI_LWO_COLR:
case AI_LWO_COLR: {
{ AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,COLR,3);
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,COLR,3); surf.mColor.r = GetU1() / 255.0f;
surf.mColor.r = GetU1() / 255.0f; surf.mColor.g = GetU1() / 255.0f;
surf.mColor.g = GetU1() / 255.0f; surf.mColor.b = GetU1() / 255.0f;
surf.mColor.b = GetU1() / 255.0f; break;
break;
}
// diffuse strength ...
case AI_LWO_DIFF:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,DIFF,2);
surf.mDiffuseValue = GetU2() / 255.0f;
break;
}
// specular strength ...
case AI_LWO_SPEC:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPEC,2);
surf.mSpecularValue = GetU2() / 255.0f;
break;
}
// luminosity ...
case AI_LWO_LUMI:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LUMI,2);
surf.mLuminosity = GetU2() / 255.0f;
break;
}
// transparency
case AI_LWO_TRAN:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TRAN,2);
surf.mTransparency = GetU2() / 255.0f;
break;
}
// surface flags
case AI_LWO_FLAG:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,FLAG,2);
uint16_t flag = GetU2();
if (flag & 0x4 ) surf.mMaximumSmoothAngle = 1.56207f;
if (flag & 0x8 ) surf.mColorHighlights = 1.f;
if (flag & 0x100) surf.bDoubleSided = true;
break;
}
// maximum smoothing angle
case AI_LWO_SMAN:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SMAN,4);
surf.mMaximumSmoothAngle = std::fabs( GetF4() );
break;
}
// glossiness
case AI_LWO_GLOS:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,GLOS,2);
surf.mGlossiness = (float)GetU2();
break;
}
// color texture
case AI_LWO_CTEX:
{
pTex = SetupNewTextureLWOB(surf.mColorTextures,
head.length);
break;
}
// diffuse texture
case AI_LWO_DTEX:
{
pTex = SetupNewTextureLWOB(surf.mDiffuseTextures,
head.length);
break;
}
// specular texture
case AI_LWO_STEX:
{
pTex = SetupNewTextureLWOB(surf.mSpecularTextures,
head.length);
break;
}
// bump texture
case AI_LWO_BTEX:
{
pTex = SetupNewTextureLWOB(surf.mBumpTextures,
head.length);
break;
}
// transparency texture
case AI_LWO_TTEX:
{
pTex = SetupNewTextureLWOB(surf.mOpacityTextures,
head.length);
break;
}
// texture path
case AI_LWO_TIMG:
{
if (pTex) {
GetS0(pTex->mFileName,head.length);
} else {
ASSIMP_LOG_WARN("LWOB: Unexpected TIMG chunk");
} }
break; // diffuse strength ...
} case AI_LWO_DIFF:
// texture strength {
case AI_LWO_TVAL: AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,DIFF,2);
{ surf.mDiffuseValue = GetU2() / 255.0f;
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TVAL,1); break;
if (pTex) {
pTex->mStrength = (float)GetU1()/ 255.f;
} else {
ASSIMP_LOG_ERROR("LWOB: Unexpected TVAL chunk");
} }
break; // specular strength ...
} case AI_LWO_SPEC:
// texture flags {
case AI_LWO_TFLG: AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SPEC,2);
{ surf.mSpecularValue = GetU2() / 255.0f;
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TFLG,2); break;
}
if (nullptr != pTex) { // luminosity ...
const uint16_t s = GetU2(); case AI_LWO_LUMI:
if (s & 1) {
pTex->majorAxis = LWO::Texture::AXIS_X; AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,LUMI,2);
else if (s & 2) surf.mLuminosity = GetU2() / 255.0f;
pTex->majorAxis = LWO::Texture::AXIS_Y; break;
else if (s & 4) }
pTex->majorAxis = LWO::Texture::AXIS_Z; // transparency
case AI_LWO_TRAN:
if (s & 16) { {
ASSIMP_LOG_WARN("LWOB: Ignoring \'negate\' flag on texture"); AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TRAN,2);
surf.mTransparency = GetU2() / 255.0f;
break;
}
// surface flags
case AI_LWO_FLAG:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,FLAG,2);
uint16_t flag = GetU2();
if (flag & 0x4 ) surf.mMaximumSmoothAngle = 1.56207f;
if (flag & 0x8 ) surf.mColorHighlights = 1.f;
if (flag & 0x100) surf.bDoubleSided = true;
break;
}
// maximum smoothing angle
case AI_LWO_SMAN:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,SMAN,4);
surf.mMaximumSmoothAngle = std::fabs( GetF4() );
break;
}
// glossiness
case AI_LWO_GLOS:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,GLOS,2);
surf.mGlossiness = (float)GetU2();
break;
}
// color texture
case AI_LWO_CTEX:
{
pTex = SetupNewTextureLWOB(surf.mColorTextures,
head.length);
break;
}
// diffuse texture
case AI_LWO_DTEX:
{
pTex = SetupNewTextureLWOB(surf.mDiffuseTextures,
head.length);
break;
}
// specular texture
case AI_LWO_STEX:
{
pTex = SetupNewTextureLWOB(surf.mSpecularTextures,
head.length);
break;
}
// bump texture
case AI_LWO_BTEX:
{
pTex = SetupNewTextureLWOB(surf.mBumpTextures,
head.length);
break;
}
// transparency texture
case AI_LWO_TTEX:
{
pTex = SetupNewTextureLWOB(surf.mOpacityTextures,
head.length);
break;
}
// texture path
case AI_LWO_TIMG:
{
if (pTex) {
GetS0(pTex->mFileName,head.length);
} else {
ASSIMP_LOG_WARN("LWOB: Unexpected TIMG chunk");
} }
break;
} }
else { // texture strength
ASSIMP_LOG_WARN("LWOB: Unexpected TFLG chunk"); case AI_LWO_TVAL:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TVAL,1);
if (pTex) {
pTex->mStrength = (float)GetU1()/ 255.f;
} else {
ASSIMP_LOG_ERROR("LWOB: Unexpected TVAL chunk");
}
break;
}
// texture flags
case AI_LWO_TFLG:
{
AI_LWO_VALIDATE_CHUNK_LENGTH(head.length,TFLG,2);
if (nullptr != pTex) {
const uint16_t s = GetU2();
if (s & 1)
pTex->majorAxis = LWO::Texture::AXIS_X;
else if (s & 2)
pTex->majorAxis = LWO::Texture::AXIS_Y;
else if (s & 4)
pTex->majorAxis = LWO::Texture::AXIS_Z;
if (s & 16) {
ASSIMP_LOG_WARN("LWOB: Ignoring \'negate\' flag on texture");
}
}
else {
ASSIMP_LOG_WARN("LWOB: Unexpected TFLG chunk");
}
break;
} }
break;
}
} }
mFileBuffer = next; mFileBuffer = next;
} }

View File

@ -63,7 +63,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"LightWave Scene Importer", "LightWave Scene Importer",
"", "",
"", "",
@ -139,10 +139,6 @@ LWSImporter::LWSImporter() :
// nothing to do here // nothing to do here
} }
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
LWSImporter::~LWSImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool LWSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { bool LWSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {

View File

@ -174,7 +174,7 @@ struct NodeDesc {
class LWSImporter : public BaseImporter { class LWSImporter : public BaseImporter {
public: public:
LWSImporter(); LWSImporter();
~LWSImporter() override; ~LWSImporter() override = default;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
// Check whether we can read a specific file // Check whether we can read a specific file

View File

@ -85,7 +85,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
are listed in aiScene->mRootNode->children, but all without meshes are listed in aiScene->mRootNode->children, but all without meshes
*/ */
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Model 3D Importer", "Model 3D Importer",
"", "",
"", "",

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team Copyright (c) 2006-2022, assimp team
All rights reserved. All rights reserved.
Redistribution and use of this software in source and binary forms, Redistribution and use of this software in source and binary forms,
@ -41,7 +39,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
*/ */
#ifndef ASSIMP_BUILD_NO_MD2_IMPORTER #ifndef ASSIMP_BUILD_NO_MD2_IMPORTER
/** @file Implementation of the MD2 importer class */ /** @file Implementation of the MD2 importer class */
@ -65,7 +62,7 @@ using namespace Assimp::MD2;
# define ARRAYSIZE(_array) (int(sizeof(_array) / sizeof(_array[0]))) # define ARRAYSIZE(_array) (int(sizeof(_array) / sizeof(_array[0])))
#endif #endif
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Quake II Mesh Importer", "Quake II Mesh Importer",
"", "",
"", "",
@ -79,7 +76,7 @@ static const aiImporterDesc desc = {
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Helper function to lookup a normal in Quake 2's precalculated table // Helper function to lookup a normal in Quake 2's pre-calculated table
void MD2::LookupNormalIndex(uint8_t iNormalIndex,aiVector3D& vOut) void MD2::LookupNormalIndex(uint8_t iNormalIndex,aiVector3D& vOut)
{ {
// make sure the normal index has a valid value // make sure the normal index has a valid value
@ -100,10 +97,6 @@ MD2Importer::MD2Importer()
fileSize() fileSize()
{} {}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
MD2Importer::~MD2Importer() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool MD2Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const bool MD2Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const

View File

@ -63,7 +63,7 @@ using namespace MD2;
class MD2Importer : public BaseImporter { class MD2Importer : public BaseImporter {
public: public:
MD2Importer(); MD2Importer();
~MD2Importer() override; ~MD2Importer() override = default;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.

View File

@ -70,7 +70,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Quake III Mesh Importer", "Quake III Mesh Importer",
"", "",
"", "",

View File

@ -64,7 +64,7 @@ using namespace Assimp;
// Minimum weight value. Weights inside [-n ... n] are ignored // Minimum weight value. Weights inside [-n ... n] are ignored
#define AI_MD5_WEIGHT_EPSILON Math::getEpsilon<float>() #define AI_MD5_WEIGHT_EPSILON Math::getEpsilon<float>()
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Doom 3 / MD5 Mesh Importer", "Doom 3 / MD5 Mesh Importer",
"", "",
"", "",
@ -92,10 +92,6 @@ MD5Importer::MD5Importer() :
// empty // empty
} }
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
MD5Importer::~MD5Importer() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool MD5Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { bool MD5Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {

View File

@ -65,7 +65,7 @@ using namespace Assimp::MD5;
class MD5Importer : public BaseImporter { class MD5Importer : public BaseImporter {
public: public:
MD5Importer(); MD5Importer();
~MD5Importer() override; ~MD5Importer() override = default;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.

View File

@ -60,7 +60,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
using namespace Assimp::MDC; using namespace Assimp::MDC;
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Return To Castle Wolfenstein Mesh Importer", "Return To Castle Wolfenstein Mesh Importer",
"", "",
"", "",
@ -103,10 +103,6 @@ MDCImporter::MDCImporter() :
// empty // empty
} }
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
MDCImporter::~MDCImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool MDCImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { bool MDCImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {

View File

@ -62,7 +62,7 @@ using namespace MDC;
class MDCImporter : public BaseImporter { class MDCImporter : public BaseImporter {
public: public:
MDCImporter(); MDCImporter();
~MDCImporter() override; ~MDCImporter() override = default;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.

View File

@ -65,7 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Quake Mesh / 3D GameStudio Mesh Importer", "Quake Mesh / 3D GameStudio Mesh Importer",
"", "",
"", "",
@ -96,10 +96,6 @@ MDLImporter::MDLImporter() :
// empty // empty
} }
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
MDLImporter::~MDLImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool MDLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { bool MDLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {

View File

@ -39,10 +39,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------- ----------------------------------------------------------------------
*/ */
/// @file MDLLoader.h
/** @file MDLLoader.h /// @brief Declaration of the loader for MDL files
* @brief Declaration of the loader for MDL files
*/
#pragma once #pragma once
#ifndef AI_MDLLOADER_H_INCLUDED #ifndef AI_MDLLOADER_H_INCLUDED
#define AI_MDLLOADER_H_INCLUDED #define AI_MDLLOADER_H_INCLUDED
@ -83,11 +81,10 @@ using namespace MDL;
* them all with a single 1000-line function-beast. However, it has been * them all with a single 1000-line function-beast. However, it has been
* split into several code paths to make the code easier to read and maintain. * split into several code paths to make the code easier to read and maintain.
*/ */
class MDLImporter : public BaseImporter class MDLImporter : public BaseImporter {
{
public: public:
MDLImporter(); MDLImporter();
~MDLImporter() override; ~MDLImporter() override = default;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.

View File

@ -57,7 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory> #include <memory>
#include <sstream> #include <sstream>
static const aiImporterDesc desc = { "MMD Importer", static constexpr aiImporterDesc desc = { "MMD Importer",
"", "",
"", "",
"surfaces supported?", "surfaces supported?",
@ -81,10 +81,6 @@ MMDImporter::MMDImporter() :
m_strAbsPath = io.getOsSeparator(); m_strAbsPath = io.getOsSeparator();
} }
// ------------------------------------------------------------------------------------------------
// Destructor.
MMDImporter::~MMDImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns true, if file is an pmx file. // Returns true, if file is an pmx file.
bool MMDImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool MMDImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler,

View File

@ -50,46 +50,34 @@ struct aiMesh;
namespace Assimp { namespace Assimp {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
/// \class MMDImporter /// @class MMDImporter
/// \brief Imports MMD a pmx/pmd/vmd file /// @brief Imports MMD a pmx/pmd/vmd file
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
class MMDImporter : public BaseImporter { class MMDImporter : public BaseImporter {
public: public:
/// \brief Default constructor /// @brief Default constructor
MMDImporter(); MMDImporter();
/// \brief Destructor /// @brief Destructor
~MMDImporter() override; ~MMDImporter() override = default;
public: public:
/// \brief Returns whether the class can handle the format of the given file. /// @brief Returns whether the class can handle the format of the given file.
/// \remark See BaseImporter::CanRead() for details. /// @remark See BaseImporter::CanRead() for details.
bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const override; bool CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const override;
private: private:
//! \brief Appends the supported extension.
const aiImporterDesc* GetInfo() const override; const aiImporterDesc* GetInfo() const override;
//! \brief File import implementation.
void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override; void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override;
//! \brief Create the data from imported content.
void CreateDataFromImport(const pmx::PmxModel* pModel, aiScene* pScene); void CreateDataFromImport(const pmx::PmxModel* pModel, aiScene* pScene);
//! \brief Create the mesh
aiMesh* CreateMesh(const pmx::PmxModel* pModel, const int indexStart, const int indexCount); aiMesh* CreateMesh(const pmx::PmxModel* pModel, const int indexStart, const int indexCount);
//! \brief Create the material
aiMaterial* CreateMaterial(const pmx::PmxMaterial* pMat, const pmx::PmxModel* pModel); aiMaterial* CreateMaterial(const pmx::PmxMaterial* pMat, const pmx::PmxModel* pModel);
private: private:
//! Data buffer
std::vector<char> m_Buffer; std::vector<char> m_Buffer;
//! Absolute pathname of model in file system
std::string m_strAbsPath; std::string m_strAbsPath;
}; };
// ------------------------------------------------------------------------------------------------
} // Namespace Assimp } // Namespace Assimp

View File

@ -60,7 +60,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Milkshape 3D Importer", "Milkshape 3D Importer",
"", "",
"", "",
@ -84,9 +84,6 @@ MS3DImporter::MS3DImporter()
: mScene() : mScene()
{} {}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
MS3DImporter::~MS3DImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool MS3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const bool MS3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const

View File

@ -48,6 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/BaseImporter.h> #include <assimp/BaseImporter.h>
#include <assimp/StreamReader.h> #include <assimp/StreamReader.h>
struct aiNode; struct aiNode;
namespace Assimp { namespace Assimp {
@ -58,7 +59,7 @@ namespace Assimp {
class MS3DImporter : public BaseImporter { class MS3DImporter : public BaseImporter {
public: public:
MS3DImporter(); MS3DImporter();
~MS3DImporter() override; ~MS3DImporter() override = default;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.

View File

@ -43,8 +43,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* Implementation of the NDO importer class. * Implementation of the NDO importer class.
*/ */
#ifndef ASSIMP_BUILD_NO_NDO_IMPORTER #ifndef ASSIMP_BUILD_NO_NDO_IMPORTER
#include "NDOLoader.h" #include "NDOLoader.h"
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
@ -56,7 +56,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Nendo Mesh Importer", "Nendo Mesh Importer",
"", "",
"", "",
@ -69,14 +69,6 @@ static const aiImporterDesc desc = {
"ndo" "ndo"
}; };
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
NDOImporter::NDOImporter() = default;
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
NDOImporter::~NDOImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool NDOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const bool NDOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const

View File

@ -65,8 +65,8 @@ class Importer;
*/ */
class NDOImporter : public BaseImporter { class NDOImporter : public BaseImporter {
public: public:
NDOImporter(); NDOImporter() = default;
~NDOImporter() override; ~NDOImporter() override = default;
//! Represents a single edge //! Represents a single edge
struct Edge { struct Edge {

View File

@ -56,9 +56,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <memory> #include <memory>
using namespace Assimp; namespace Assimp {
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Neutral File Format Importer", "Neutral File Format Importer",
"", "",
"", "",
@ -71,14 +71,6 @@ static const aiImporterDesc desc = {
"enff nff" "enff nff"
}; };
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
NFFImporter::NFFImporter() = default;
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
NFFImporter::~NFFImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool NFFImporter::CanRead(const std::string & pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { bool NFFImporter::CanRead(const std::string & pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
@ -94,7 +86,7 @@ const aiImporterDesc *NFFImporter::GetInfo() const {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
#define AI_NFF_PARSE_FLOAT(f) \ #define AI_NFF_PARSE_FLOAT(f) \
SkipSpaces(&sz); \ SkipSpaces(&sz); \
if (!::IsLineEnd(*sz)) sz = fast_atoreal_move<ai_real>(sz, (ai_real &)f); if (!IsLineEnd(*sz)) sz = fast_atoreal_move<ai_real>(sz, (ai_real &)f);
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
#define AI_NFF_PARSE_TRIPLE(v) \ #define AI_NFF_PARSE_TRIPLE(v) \
@ -338,8 +330,8 @@ void NFFImporter::InternReadFile(const std::string &pFile,
break; break;
} }
// read the numbr of vertices // read the number of vertices
unsigned int num = ::strtoul10(sz, &sz); unsigned int num = strtoul10(sz, &sz);
// temporary storage // temporary storage
std::vector<aiColor4D> tempColors; std::vector<aiColor4D> tempColors;
@ -365,7 +357,7 @@ void NFFImporter::InternReadFile(const std::string &pFile,
// color definition // color definition
if (TokenMatch(sz, "0x", 2)) { if (TokenMatch(sz, "0x", 2)) {
hasColor = true; hasColor = true;
unsigned int numIdx = ::strtoul16(sz, &sz); unsigned int numIdx = strtoul16(sz, &sz);
aiColor4D clr; aiColor4D clr;
clr.a = 1.f; clr.a = 1.f;
@ -403,15 +395,16 @@ void NFFImporter::InternReadFile(const std::string &pFile,
} }
AI_NFF2_GET_NEXT_TOKEN(); AI_NFF2_GET_NEXT_TOKEN();
if (!num) throw DeadlyImportError("NFF2: There are zero vertices"); if (!num)
num = ::strtoul10(sz, &sz); throw DeadlyImportError("NFF2: There are zero vertices");
num = strtoul10(sz, &sz);
std::vector<unsigned int> tempIdx; std::vector<unsigned int> tempIdx;
tempIdx.reserve(10); tempIdx.reserve(10);
for (unsigned int i = 0; i < num; ++i) { for (unsigned int i = 0; i < num; ++i) {
AI_NFF2_GET_NEXT_TOKEN(); AI_NFF2_GET_NEXT_TOKEN();
SkipSpaces(line, &sz); SkipSpaces(line, &sz);
unsigned int numIdx = ::strtoul10(sz, &sz); unsigned int numIdx = strtoul10(sz, &sz);
// read all faces indices // read all faces indices
if (numIdx) { if (numIdx) {
@ -421,7 +414,7 @@ void NFFImporter::InternReadFile(const std::string &pFile,
for (unsigned int a = 0; a < numIdx; ++a) { for (unsigned int a = 0; a < numIdx; ++a) {
SkipSpaces(sz, &sz); SkipSpaces(sz, &sz);
unsigned int m = ::strtoul10(sz, &sz); unsigned int m = strtoul10(sz, &sz);
if (m >= (unsigned int)tempPositions.size()) { if (m >= (unsigned int)tempPositions.size()) {
ASSIMP_LOG_ERROR("NFF2: Vertex index overflow"); ASSIMP_LOG_ERROR("NFF2: Vertex index overflow");
m = 0; m = 0;
@ -446,7 +439,7 @@ void NFFImporter::InternReadFile(const std::string &pFile,
if (TokenMatch(sz, "0x", 2)) { if (TokenMatch(sz, "0x", 2)) {
hasColor = true; hasColor = true;
const char *sz2 = sz; const char *sz2 = sz;
numIdx = ::strtoul16(sz, &sz); numIdx = strtoul16(sz, &sz);
const unsigned int diff = (unsigned int)(sz - sz2); const unsigned int diff = (unsigned int)(sz - sz2);
// 0xRRGGBB // 0xRRGGBB
@ -518,7 +511,7 @@ void NFFImporter::InternReadFile(const std::string &pFile,
// Material ID? // Material ID?
else if (!materialTable.empty() && TokenMatch(sz, "matid", 5)) { else if (!materialTable.empty() && TokenMatch(sz, "matid", 5)) {
SkipSpaces(&sz); SkipSpaces(&sz);
matIdx = ::strtoul10(sz, &sz); matIdx = strtoul10(sz, &sz);
if (matIdx >= materialTable.size()) { if (matIdx >= materialTable.size()) {
ASSIMP_LOG_ERROR("NFF2: Material index overflow."); ASSIMP_LOG_ERROR("NFF2: Material index overflow.");
matIdx = 0; matIdx = 0;
@ -1165,4 +1158,6 @@ void NFFImporter::InternReadFile(const std::string &pFile,
pScene->mRootNode = root; pScene->mRootNode = root;
} }
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_NFF_IMPORTER #endif // !! ASSIMP_BUILD_NO_NFF_IMPORTER

View File

@ -63,8 +63,8 @@ namespace Assimp {
*/ */
class NFFImporter : public BaseImporter { class NFFImporter : public BaseImporter {
public: public:
NFFImporter(); NFFImporter() = default;
~NFFImporter() override; ~NFFImporter() override = default;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.

View File

@ -43,7 +43,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
* @brief Implementation of the OFF importer class * @brief Implementation of the OFF importer class
*/ */
#ifndef ASSIMP_BUILD_NO_OFF_IMPORTER #ifndef ASSIMP_BUILD_NO_OFF_IMPORTER
// internal headers // internal headers
@ -56,9 +55,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
using namespace Assimp; namespace Assimp {
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"OFF Importer", "OFF Importer",
"", "",
"", "",
@ -71,99 +70,92 @@ static const aiImporterDesc desc = {
"off" "off"
}; };
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
OFFImporter::OFFImporter() = default;
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
OFFImporter::~OFFImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool OFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const bool OFFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
{ static const char *tokens[] = { "off" };
static const char* tokens[] = { "off" }; return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens), 3);
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,AI_COUNT_OF(tokens),3);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
const aiImporterDesc* OFFImporter::GetInfo () const const aiImporterDesc *OFFImporter::GetInfo() const {
{
return &desc; return &desc;
} }
// skip blank space, lines and comments // skip blank space, lines and comments
static void NextToken(const char **car, const char* end) { static void NextToken(const char **car, const char *end) {
SkipSpacesAndLineEnd(car);
while (*car < end && (**car == '#' || **car == '\n' || **car == '\r')) {
SkipLine(car);
SkipSpacesAndLineEnd(car); SkipSpacesAndLineEnd(car);
} while (*car < end && (**car == '#' || **car == '\n' || **car == '\r')) {
SkipLine(car);
SkipSpacesAndLineEnd(car);
}
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { void OFFImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile, "rb")); std::unique_ptr<IOStream> file(pIOHandler->Open(pFile, "rb"));
// Check whether we can read from the file // Check whether we can read from the file
if (file == nullptr) { if (file == nullptr) {
throw DeadlyImportError("Failed to open OFF file ", pFile, "."); throw DeadlyImportError("Failed to open OFF file ", pFile, ".");
} }
// allocate storage and copy the contents of the file to a memory buffer // allocate storage and copy the contents of the file to a memory buffer
std::vector<char> mBuffer2; std::vector<char> mBuffer2;
TextFileToBuffer(file.get(),mBuffer2); TextFileToBuffer(file.get(), mBuffer2);
const char* buffer = &mBuffer2[0]; const char *buffer = &mBuffer2[0];
// Proper OFF header parser. We only implement normal loading for now. // Proper OFF header parser. We only implement normal loading for now.
bool hasTexCoord = false, hasNormals = false, hasColors = false; bool hasTexCoord = false, hasNormals = false, hasColors = false;
bool hasHomogenous = false, hasDimension = false; bool hasHomogenous = false, hasDimension = false;
unsigned int dimensions = 3; unsigned int dimensions = 3;
const char* car = buffer; const char *car = buffer;
const char* end = buffer + mBuffer2.size(); const char *end = buffer + mBuffer2.size();
NextToken(&car, end); NextToken(&car, end);
if (car < end - 2 && car[0] == 'S' && car[1] == 'T') { if (car < end - 2 && car[0] == 'S' && car[1] == 'T') {
hasTexCoord = true; car += 2; hasTexCoord = true;
car += 2;
} }
if (car < end - 1 && car[0] == 'C') { if (car < end - 1 && car[0] == 'C') {
hasColors = true; car++; hasColors = true;
car++;
} }
if (car < end- 1 && car[0] == 'N') { if (car < end - 1 && car[0] == 'N') {
hasNormals = true; car++; hasNormals = true;
car++;
} }
if (car < end - 1 && car[0] == '4') { if (car < end - 1 && car[0] == '4') {
hasHomogenous = true; car++; hasHomogenous = true;
car++;
} }
if (car < end - 1 && car[0] == 'n') { if (car < end - 1 && car[0] == 'n') {
hasDimension = true; car++; hasDimension = true;
car++;
} }
if (car < end - 3 && car[0] == 'O' && car[1] == 'F' && car[2] == 'F') { if (car < end - 3 && car[0] == 'O' && car[1] == 'F' && car[2] == 'F') {
car += 3; car += 3;
NextToken(&car, end); NextToken(&car, end);
} else { } else {
// in case there is no OFF header (which is allowed by the // in case there is no OFF header (which is allowed by the
// specification...), then we might have unintentionally read an // specification...), then we might have unintentionally read an
// additional dimension from the primitive count fields // additional dimension from the primitive count fields
dimensions = 3; dimensions = 3;
hasHomogenous = false; hasHomogenous = false;
NextToken(&car, end); NextToken(&car, end);
// at this point the next token should be an integer number // at this point the next token should be an integer number
if (car >= end - 1 || *car < '0' || *car > '9') { if (car >= end - 1 || *car < '0' || *car > '9') {
throw DeadlyImportError("OFF: Header is invalid"); throw DeadlyImportError("OFF: Header is invalid");
} }
} }
if (hasDimension) { if (hasDimension) {
dimensions = strtoul10(car, &car); dimensions = strtoul10(car, &car);
NextToken(&car, end); NextToken(&car, end);
} }
if (dimensions > 3) { if (dimensions > 3) {
throw DeadlyImportError throw DeadlyImportError("OFF: Number of vertex coordinates higher than 3 unsupported");
("OFF: Number of vertex coordinates higher than 3 unsupported");
} }
NextToken(&car, end); NextToken(&car, end);
@ -171,7 +163,7 @@ void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
NextToken(&car, end); NextToken(&car, end);
const unsigned int numFaces = strtoul10(car, &car); const unsigned int numFaces = strtoul10(car, &car);
NextToken(&car, end); NextToken(&car, end);
strtoul10(car, &car); // skip edge count strtoul10(car, &car); // skip edge count
NextToken(&car, end); NextToken(&car, end);
if (!numVertices) { if (!numVertices) {
@ -182,13 +174,13 @@ void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
} }
pScene->mNumMeshes = 1; pScene->mNumMeshes = 1;
pScene->mMeshes = new aiMesh*[ pScene->mNumMeshes ]; pScene->mMeshes = new aiMesh *[pScene->mNumMeshes];
aiMesh* mesh = new aiMesh(); aiMesh *mesh = new aiMesh();
pScene->mMeshes[0] = mesh; pScene->mMeshes[0] = mesh;
mesh->mNumFaces = numFaces; mesh->mNumFaces = numFaces;
aiFace* faces = new aiFace[mesh->mNumFaces]; aiFace *faces = new aiFace[mesh->mNumFaces];
mesh->mFaces = faces; mesh->mFaces = faces;
mesh->mNumVertices = numVertices; mesh->mNumVertices = numVertices;
@ -206,100 +198,101 @@ void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
// now read all vertex lines // now read all vertex lines
for (unsigned int i = 0; i < numVertices; ++i) { for (unsigned int i = 0; i < numVertices; ++i) {
if(!GetNextLine(buffer, line)) { if (!GetNextLine(buffer, line)) {
ASSIMP_LOG_ERROR("OFF: The number of verts in the header is incorrect"); ASSIMP_LOG_ERROR("OFF: The number of verts in the header is incorrect");
break; break;
} }
aiVector3D& v = mesh->mVertices[i]; aiVector3D &v = mesh->mVertices[i];
sz = line; sz = line;
// helper array to write a for loop over possible dimension values // helper array to write a for loop over possible dimension values
ai_real* vec[3] = {&v.x, &v.y, &v.z}; ai_real *vec[3] = { &v.x, &v.y, &v.z };
// stop at dimensions: this allows loading 1D or 2D coordinate vertices // stop at dimensions: this allows loading 1D or 2D coordinate vertices
for (unsigned int dim = 0; dim < dimensions; ++dim ) { for (unsigned int dim = 0; dim < dimensions; ++dim) {
SkipSpaces(&sz); SkipSpaces(&sz);
sz = fast_atoreal_move<ai_real>(sz, *vec[dim]); sz = fast_atoreal_move<ai_real>(sz, *vec[dim]);
} }
// if has homogeneous coordinate, divide others by this one // if has homogeneous coordinate, divide others by this one
if (hasHomogenous) { if (hasHomogenous) {
SkipSpaces(&sz); SkipSpaces(&sz);
ai_real w = 1.; ai_real w = 1.;
sz = fast_atoreal_move<ai_real>(sz, w); sz = fast_atoreal_move<ai_real>(sz, w);
for (unsigned int dim = 0; dim < dimensions; ++dim ) { for (unsigned int dim = 0; dim < dimensions; ++dim) {
*(vec[dim]) /= w; *(vec[dim]) /= w;
} }
} }
// read optional normals // read optional normals
if (hasNormals) { if (hasNormals) {
aiVector3D& n = mesh->mNormals[i]; aiVector3D &n = mesh->mNormals[i];
SkipSpaces(&sz); SkipSpaces(&sz);
sz = fast_atoreal_move<ai_real>(sz,(ai_real&)n.x); sz = fast_atoreal_move<ai_real>(sz, (ai_real &)n.x);
SkipSpaces(&sz); SkipSpaces(&sz);
sz = fast_atoreal_move<ai_real>(sz,(ai_real&)n.y); sz = fast_atoreal_move<ai_real>(sz, (ai_real &)n.y);
SkipSpaces(&sz); SkipSpaces(&sz);
fast_atoreal_move<ai_real>(sz,(ai_real&)n.z); fast_atoreal_move<ai_real>(sz, (ai_real &)n.z);
} }
// reading colors is a pain because the specification says it can be // reading colors is a pain because the specification says it can be
// integers or floats, and any number of them between 1 and 4 included, // integers or floats, and any number of them between 1 and 4 included,
// until the next comment or end of line // until the next comment or end of line
// in theory should be testing type ! // in theory should be testing type !
if (hasColors) { if (hasColors) {
aiColor4D& c = mesh->mColors[0][i]; aiColor4D &c = mesh->mColors[0][i];
SkipSpaces(&sz); SkipSpaces(&sz);
sz = fast_atoreal_move<ai_real>(sz,(ai_real&)c.r); sz = fast_atoreal_move<ai_real>(sz, (ai_real &)c.r);
if (*sz != '#' && *sz != '\n' && *sz != '\r') { if (*sz != '#' && *sz != '\n' && *sz != '\r') {
SkipSpaces(&sz); SkipSpaces(&sz);
sz = fast_atoreal_move<ai_real>(sz,(ai_real&)c.g); sz = fast_atoreal_move<ai_real>(sz, (ai_real &)c.g);
} else { } else {
c.g = 0.; c.g = 0.;
} }
if (*sz != '#' && *sz != '\n' && *sz != '\r') { if (*sz != '#' && *sz != '\n' && *sz != '\r') {
SkipSpaces(&sz); SkipSpaces(&sz);
sz = fast_atoreal_move<ai_real>(sz,(ai_real&)c.b); sz = fast_atoreal_move<ai_real>(sz, (ai_real &)c.b);
} else { } else {
c.b = 0.; c.b = 0.;
} }
if (*sz != '#' && *sz != '\n' && *sz != '\r') { if (*sz != '#' && *sz != '\n' && *sz != '\r') {
SkipSpaces(&sz); SkipSpaces(&sz);
sz = fast_atoreal_move<ai_real>(sz,(ai_real&)c.a); sz = fast_atoreal_move<ai_real>(sz, (ai_real &)c.a);
} else { } else {
c.a = 1.; c.a = 1.;
} }
} }
if (hasTexCoord) { if (hasTexCoord) {
aiVector3D& t = mesh->mTextureCoords[0][i]; aiVector3D &t = mesh->mTextureCoords[0][i];
SkipSpaces(&sz); SkipSpaces(&sz);
sz = fast_atoreal_move<ai_real>(sz,(ai_real&)t.x); sz = fast_atoreal_move<ai_real>(sz, (ai_real &)t.x);
SkipSpaces(&sz); SkipSpaces(&sz);
fast_atoreal_move<ai_real>(sz,(ai_real&)t.y); fast_atoreal_move<ai_real>(sz, (ai_real &)t.y);
} }
} }
// load faces with their indices // load faces with their indices
faces = mesh->mFaces; faces = mesh->mFaces;
for (unsigned int i = 0; i < numFaces; ) { for (unsigned int i = 0; i < numFaces;) {
if(!GetNextLine(buffer,line)) { if (!GetNextLine(buffer, line)) {
ASSIMP_LOG_ERROR("OFF: The number of faces in the header is incorrect"); ASSIMP_LOG_ERROR("OFF: The number of faces in the header is incorrect");
throw DeadlyImportError("OFF: The number of faces in the header is incorrect"); throw DeadlyImportError("OFF: The number of faces in the header is incorrect");
} }
unsigned int idx; unsigned int idx;
sz = line; SkipSpaces(&sz); sz = line;
idx = strtoul10(sz,&sz); SkipSpaces(&sz);
if(!idx || idx > 9) { idx = strtoul10(sz, &sz);
ASSIMP_LOG_ERROR("OFF: Faces with zero indices aren't allowed"); if (!idx || idx > 9) {
ASSIMP_LOG_ERROR("OFF: Faces with zero indices aren't allowed");
--mesh->mNumFaces; --mesh->mNumFaces;
++i; ++i;
continue; continue;
} }
faces->mNumIndices = idx; faces->mNumIndices = idx;
faces->mIndices = new unsigned int[faces->mNumIndices]; faces->mIndices = new unsigned int[faces->mNumIndices];
for (unsigned int m = 0; m < faces->mNumIndices;++m) { for (unsigned int m = 0; m < faces->mNumIndices; ++m) {
SkipSpaces(&sz); SkipSpaces(&sz);
idx = strtoul10(sz,&sz); idx = strtoul10(sz, &sz);
if (idx >= numVertices) { if (idx >= numVertices) {
ASSIMP_LOG_ERROR("OFF: Vertex index is out of range"); ASSIMP_LOG_ERROR("OFF: Vertex index is out of range");
idx = numVertices - 1; idx = numVertices - 1;
@ -314,20 +307,22 @@ void OFFImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
pScene->mRootNode = new aiNode(); pScene->mRootNode = new aiNode();
pScene->mRootNode->mName.Set("<OFFRoot>"); pScene->mRootNode->mName.Set("<OFFRoot>");
pScene->mRootNode->mNumMeshes = 1; pScene->mRootNode->mNumMeshes = 1;
pScene->mRootNode->mMeshes = new unsigned int [pScene->mRootNode->mNumMeshes]; pScene->mRootNode->mMeshes = new unsigned int[pScene->mRootNode->mNumMeshes];
pScene->mRootNode->mMeshes[0] = 0; pScene->mRootNode->mMeshes[0] = 0;
// generate a default material // generate a default material
pScene->mNumMaterials = 1; pScene->mNumMaterials = 1;
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials]; pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials];
aiMaterial* pcMat = new aiMaterial(); aiMaterial *pcMat = new aiMaterial();
aiColor4D clr( ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 0.6 ), ai_real( 1.0 ) ); aiColor4D clr(ai_real(0.6), ai_real(0.6), ai_real(0.6), ai_real(1.0));
pcMat->AddProperty(&clr,1,AI_MATKEY_COLOR_DIFFUSE); pcMat->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
pScene->mMaterials[0] = pcMat; pScene->mMaterials[0] = pcMat;
const int twosided = 1; const int twosided = 1;
pcMat->AddProperty(&twosided, 1, AI_MATKEY_TWOSIDED); pcMat->AddProperty(&twosided, 1, AI_MATKEY_TWOSIDED);
} }
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_OFF_IMPORTER #endif // !! ASSIMP_BUILD_NO_OFF_IMPORTER

View File

@ -57,8 +57,8 @@ namespace Assimp {
*/ */
class OFFImporter : public BaseImporter { class OFFImporter : public BaseImporter {
public: public:
OFFImporter(); OFFImporter() = default;
~OFFImporter() override; ~OFFImporter() override = default;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.

View File

@ -54,7 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/ObjMaterial.h> #include <assimp/ObjMaterial.h>
#include <memory> #include <memory>
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Wavefront Object Importer", "Wavefront Object Importer",
"", "",
"", "",
@ -78,7 +78,9 @@ using namespace std;
ObjFileImporter::ObjFileImporter() : ObjFileImporter::ObjFileImporter() :
m_Buffer(), m_Buffer(),
m_pRootObject(nullptr), m_pRootObject(nullptr),
m_strAbsPath(std::string(1, DefaultIOSystem().getOsSeparator())) {} m_strAbsPath(std::string(1, DefaultIOSystem().getOsSeparator())) {
// empty
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor. // Destructor.
@ -101,8 +103,13 @@ const aiImporterDesc *ObjFileImporter::GetInfo() const {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Obj-file import implementation // Obj-file import implementation
void ObjFileImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSystem *pIOHandler) { void ObjFileImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSystem *pIOHandler) {
if (m_pRootObject != nullptr) {
delete m_pRootObject;
m_pRootObject = nullptr;
}
// Read file into memory // Read file into memory
static const std::string mode = "rb"; static constexpr char mode[] = "rb";
auto streamCloser = [&](IOStream *pStream) { auto streamCloser = [&](IOStream *pStream) {
pIOHandler->Close(pStream); pIOHandler->Close(pStream);
}; };

View File

@ -48,7 +48,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/Importer.hpp> #include <assimp/Importer.hpp>
#include <memory> #include <memory>
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Ogre3D Mesh Importer", "Ogre3D Mesh Importer",
"", "",
"", "",

View File

@ -52,7 +52,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h> #include <assimp/scene.h>
#include <openddlparser/OpenDDLParser.h> #include <openddlparser/OpenDDLParser.h>
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Open Game Engine Exchange", "Open Game Engine Exchange",
"", "",
"", "",
@ -66,42 +66,42 @@ static const aiImporterDesc desc = {
}; };
namespace Grammar { namespace Grammar {
static const char* MetricType = "Metric"; static constexpr char MetricType[] = "Metric";
static const char *Metric_DistanceType = "distance"; static constexpr char Metric_DistanceType[] = "distance";
static const char *Metric_AngleType = "angle"; static constexpr char Metric_AngleType[] = "angle";
static const char *Metric_TimeType = "time"; static constexpr char Metric_TimeType[] = "time";
static const char *Metric_UpType = "up"; static constexpr char Metric_UpType[] = "up";
static const char *NameType = "Name"; static constexpr char NameType[] = "Name";
static const char *ObjectRefType = "ObjectRef"; static constexpr char ObjectRefType[] = "ObjectRef";
static const char *MaterialRefType = "MaterialRef"; static constexpr char MaterialRefType[] = "MaterialRef";
static const char *MetricKeyType = "key"; static constexpr char MetricKeyType[] = "key";
static const char *GeometryNodeType = "GeometryNode"; static constexpr char GeometryNodeType[] = "GeometryNode";
static const char *CameraNodeType = "CameraNode"; static constexpr char CameraNodeType[] = "CameraNode";
static const char *LightNodeType = "LightNode"; static constexpr char LightNodeType[] = "LightNode";
static const char *GeometryObjectType = "GeometryObject"; static constexpr char GeometryObjectType[] = "GeometryObject";
static const char *CameraObjectType = "CameraObject"; static constexpr char CameraObjectType[] = "CameraObject";
static const char *LightObjectType = "LightObject"; static constexpr char LightObjectType[] = "LightObject";
static const char *TransformType = "Transform"; static constexpr char TransformType[] = "Transform";
static const char *MeshType = "Mesh"; static constexpr char MeshType[] = "Mesh";
static const char *VertexArrayType = "VertexArray"; static constexpr char VertexArrayType[] = "VertexArray";
static const char *IndexArrayType = "IndexArray"; static constexpr char IndexArrayType[] = "IndexArray";
static const char *MaterialType = "Material"; static constexpr char MaterialType[] = "Material";
static const char *ColorType = "Color"; static constexpr char ColorType[] = "Color";
static const char *ParamType = "Param"; static constexpr char ParamType[] = "Param";
static const char *TextureType = "Texture"; static constexpr char TextureType[] = "Texture";
static const char *AttenType = "Atten"; static constexpr char AttenType[] = "Atten";
static const char *DiffuseColorToken = "diffuse"; static constexpr char DiffuseColorToken[] = "diffuse";
static const char *SpecularColorToken = "specular"; static constexpr char SpecularColorToken[] = "specular";
static const char *EmissionColorToken = "emission"; static constexpr char EmissionColorToken[] = "emission";
static const char *DiffuseTextureToken = "diffuse"; static constexpr char DiffuseTextureToken[] = "diffuse";
static const char *DiffuseSpecularTextureToken = "specular"; static constexpr char DiffuseSpecularTextureToken[] = "specular";
static const char *SpecularPowerTextureToken = "specular_power"; static constexpr char SpecularPowerTextureToken[] = "specular_power";
static const char *EmissionTextureToken = "emission"; static constexpr char EmissionTextureToken[] = "emission";
static const char *OpacyTextureToken = "opacity"; static constexpr char OpacyTextureToken[] = "opacity";
static const char *TransparencyTextureToken = "transparency"; static constexpr char TransparencyTextureToken[] = "transparency";
static const char *NormalTextureToken = "normal"; static constexpr char NormalTextureToken[] = "normal";
enum TokenType { enum TokenType {
NoneType = -1, NoneType = -1,
@ -139,7 +139,7 @@ namespace Grammar {
return false; return false;
} }
int idx(-1); int idx = -1;
for (size_t i = 0; i < 4; i++) { for (size_t i = 0; i < 4; i++) {
if (ValidMetricToken[i] == token) { if (ValidMetricToken[i] == token) {
idx = (int)i; idx = (int)i;

View File

@ -53,9 +53,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <memory> #include <memory>
using namespace ::Assimp; namespace Assimp {
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Stanford Polygon Library (PLY) Importer", "Stanford Polygon Library (PLY) Importer",
"", "",
"", "",
@ -71,16 +71,16 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Internal stuff // Internal stuff
namespace { namespace {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Checks that property index is within range // Checks that property index is within range
template <class T> template <class T>
inline const T &GetProperty(const std::vector<T> &props, int idx) { inline const T &GetProperty(const std::vector<T> &props, int idx) {
if (static_cast<size_t>(idx) >= props.size()) { if (static_cast<size_t>(idx) >= props.size()) {
throw DeadlyImportError("Invalid .ply file: Property index is out of range."); throw DeadlyImportError("Invalid .ply file: Property index is out of range.");
} }
return props[idx]; return props[idx];
} }
} // namespace } // namespace
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -92,10 +92,6 @@ PLYImporter::PLYImporter() :
// empty // empty
} }
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
PLYImporter::~PLYImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool PLYImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { bool PLYImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
@ -215,7 +211,7 @@ void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
throw DeadlyImportError("Invalid .ply file: Missing format specification"); throw DeadlyImportError("Invalid .ply file: Missing format specification");
} }
//free the file buffer // free the file buffer
streamedBuffer.close(); streamedBuffer.close();
if (mGeneratedMesh == nullptr) { if (mGeneratedMesh == nullptr) {
@ -376,7 +372,7 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
haveNormal = true; haveNormal = true;
} }
//Colors // Colors
aiColor4D cOut; aiColor4D cOut;
bool haveColor = false; bool haveColor = false;
if (0xFFFFFFFF != aiColors[0]) { if (0xFFFFFFFF != aiColors[0]) {
@ -415,7 +411,7 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
haveColor = true; haveColor = true;
} }
//Texture coordinates // Texture coordinates
aiVector3D tOut; aiVector3D tOut;
tOut.z = 0; tOut.z = 0;
bool haveTextureCoords = false; bool haveTextureCoords = false;
@ -431,7 +427,7 @@ void PLYImporter::LoadVertex(const PLY::Element *pcElement, const PLY::ElementIn
haveTextureCoords = true; haveTextureCoords = true;
} }
//create aiMesh if needed // create aiMesh if needed
if (nullptr == mGeneratedMesh) { if (nullptr == mGeneratedMesh) {
mGeneratedMesh = new aiMesh(); mGeneratedMesh = new aiMesh();
mGeneratedMesh->mMaterialIndex = 0; mGeneratedMesh->mMaterialIndex = 0;
@ -512,8 +508,8 @@ void PLYImporter::LoadFace(const PLY::Element *pcElement, const PLY::ElementInst
bool bIsTriStrip = false; bool bIsTriStrip = false;
// index of the material index property // index of the material index property
//unsigned int iMaterialIndex = 0xFFFFFFFF; // unsigned int iMaterialIndex = 0xFFFFFFFF;
//PLY::EDataType eType2 = EDT_Char; // PLY::EDataType eType2 = EDT_Char;
// texture coordinates // texture coordinates
unsigned int iTextureCoord = 0xFFFFFFFF; unsigned int iTextureCoord = 0xFFFFFFFF;
@ -595,7 +591,7 @@ void PLYImporter::LoadFace(const PLY::Element *pcElement, const PLY::ElementInst
if (0xFFFFFFFF != iTextureCoord) { if (0xFFFFFFFF != iTextureCoord) {
const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size(); const unsigned int iNum = (unsigned int)GetProperty(instElement->alProperties, iTextureCoord).avList.size();
//should be 6 coords // should be 6 coords
std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p = std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator p =
GetProperty(instElement->alProperties, iTextureCoord).avList.begin(); GetProperty(instElement->alProperties, iTextureCoord).avList.begin();
@ -625,7 +621,7 @@ void PLYImporter::LoadFace(const PLY::Element *pcElement, const PLY::ElementInst
// a value of -1 indicates a restart of the strip // a value of -1 indicates a restart of the strip
bool flip = false; bool flip = false;
const std::vector<PLY::PropertyInstance::ValueUnion> &quak = GetProperty(instElement->alProperties, iProperty).avList; const std::vector<PLY::PropertyInstance::ValueUnion> &quak = GetProperty(instElement->alProperties, iProperty).avList;
//pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u)); //Limits memory consumption // pvOut->reserve(pvOut->size() + quak.size() + (quak.size()>>2u)); //Limits memory consumption
int aiTable[2] = { -1, -1 }; int aiTable[2] = { -1, -1 };
for (std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator a = quak.begin(); a != quak.end(); ++a) { for (std::vector<PLY::PropertyInstance::ValueUnion>::const_iterator a = quak.begin(); a != quak.end(); ++a) {
@ -863,7 +859,7 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial *> *pvOut, std::string &de
const int two_sided = 1; const int two_sided = 1;
pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED); pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
//default texture // default texture
if (!defaultTexture.empty()) { if (!defaultTexture.empty()) {
const aiString name(defaultTexture.c_str()); const aiString name(defaultTexture.c_str());
pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0); pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0);
@ -873,7 +869,7 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial *> *pvOut, std::string &de
pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED); pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
} }
//set to wireframe, so when using this material info we can switch to points rendering // set to wireframe, so when using this material info we can switch to points rendering
if (pointsOnly) { if (pointsOnly) {
const int wireframe = 1; const int wireframe = 1;
pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME); pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME);
@ -890,7 +886,7 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial *> *pvOut, std::string &de
int iMode = (int)aiShadingMode_Gouraud; int iMode = (int)aiShadingMode_Gouraud;
pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL); pcHelper->AddProperty<int>(&iMode, 1, AI_MATKEY_SHADING_MODEL);
//generate white material most 3D engine just multiply ambient / diffuse color with actual ambient / light color // generate white material most 3D engine just multiply ambient / diffuse color with actual ambient / light color
aiColor3D clr; aiColor3D clr;
clr.b = clr.g = clr.r = 1.0f; clr.b = clr.g = clr.r = 1.0f;
pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_DIFFUSE); pcHelper->AddProperty<aiColor3D>(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
@ -906,13 +902,13 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial *> *pvOut, std::string &de
pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED); pcHelper->AddProperty(&two_sided, 1, AI_MATKEY_TWOSIDED);
} }
//default texture // default texture
if (!defaultTexture.empty()) { if (!defaultTexture.empty()) {
const aiString name(defaultTexture.c_str()); const aiString name(defaultTexture.c_str());
pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0); pcHelper->AddProperty(&name, _AI_MATKEY_TEXTURE_BASE, aiTextureType_DIFFUSE, 0);
} }
//set to wireframe, so when using this material info we can switch to points rendering // set to wireframe, so when using this material info we can switch to points rendering
if (pointsOnly) { if (pointsOnly) {
const int wireframe = 1; const int wireframe = 1;
pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME); pcHelper->AddProperty(&wireframe, 1, AI_MATKEY_ENABLE_WIREFRAME);
@ -922,4 +918,6 @@ void PLYImporter::LoadMaterial(std::vector<aiMaterial *> *pvOut, std::string &de
} }
} }
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER #endif // !! ASSIMP_BUILD_NO_PLY_IMPORTER

View File

@ -65,7 +65,7 @@ using namespace PLY;
class PLYImporter : public BaseImporter { class PLYImporter : public BaseImporter {
public: public:
PLYImporter(); PLYImporter();
~PLYImporter() override; ~PLYImporter() override = default;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.

View File

@ -65,7 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <sstream> #include <sstream>
#include <vector> #include <vector>
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Quake III BSP Importer", "Quake III BSP Importer",
"", "",
"", "",
@ -146,7 +146,11 @@ Q3BSPFileImporter::Q3BSPFileImporter() :
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor. // Destructor.
Q3BSPFileImporter::~Q3BSPFileImporter() { Q3BSPFileImporter::~Q3BSPFileImporter() {
// Clear face-to-material map clear();
}
// ------------------------------------------------------------------------------------------------
void Q3BSPFileImporter::clear() {
for (FaceMap::iterator it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it) { for (FaceMap::iterator it = m_MaterialLookupMap.begin(); it != m_MaterialLookupMap.end(); ++it) {
const std::string &matName = it->first; const std::string &matName = it->first;
if (!matName.empty()) { if (!matName.empty()) {
@ -173,6 +177,7 @@ const aiImporterDesc *Q3BSPFileImporter::GetInfo() const {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Import method. // Import method.
void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene *scene, IOSystem *ioHandler) { void Q3BSPFileImporter::InternReadFile(const std::string &rFile, aiScene *scene, IOSystem *ioHandler) {
clear();
ZipArchiveIOSystem Archive(ioHandler, rFile); ZipArchiveIOSystem Archive(ioHandler, rFile);
if (!Archive.isOpen()) { if (!Archive.isOpen()) {
throw DeadlyImportError("Failed to open file ", rFile, "."); throw DeadlyImportError("Failed to open file ", rFile, ".");

View File

@ -81,6 +81,7 @@ protected:
using FaceMapIt = std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>* >::iterator; using FaceMapIt = std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>* >::iterator;
using FaceMapConstIt = std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>*>::const_iterator; using FaceMapConstIt = std::map<std::string, std::vector<Q3BSP::sQ3BSPFace*>*>::const_iterator;
void clear();
const aiImporterDesc* GetInfo () const override; const aiImporterDesc* GetInfo () const override;
void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override; void InternReadFile(const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) override;
void separateMapName( const std::string &rImportName, std::string &rArchiveName, std::string &rMapName ); void separateMapName( const std::string &rImportName, std::string &rArchiveName, std::string &rMapName );

View File

@ -55,9 +55,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
using namespace Assimp; namespace Assimp {
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Quick3D Importer", "Quick3D Importer",
"", "",
"", "",
@ -127,7 +127,7 @@ void Q3DImporter::InternReadFile(const std::string &pFile,
std::vector<Material> materials; std::vector<Material> materials;
try { try {
materials.reserve(numMats); materials.reserve(numMats);
} catch(const std::bad_alloc&) { } catch (const std::bad_alloc &) {
ASSIMP_LOG_ERROR("Invalid alloc for materials."); ASSIMP_LOG_ERROR("Invalid alloc for materials.");
throw DeadlyImportError("Invalid Quick3D-file, material allocation failed."); throw DeadlyImportError("Invalid Quick3D-file, material allocation failed.");
} }
@ -135,7 +135,7 @@ void Q3DImporter::InternReadFile(const std::string &pFile,
std::vector<Mesh> meshes; std::vector<Mesh> meshes;
try { try {
meshes.reserve(numMeshes); meshes.reserve(numMeshes);
} catch(const std::bad_alloc&) { } catch (const std::bad_alloc &) {
ASSIMP_LOG_ERROR("Invalid alloc for meshes."); ASSIMP_LOG_ERROR("Invalid alloc for meshes.");
throw DeadlyImportError("Invalid Quick3D-file, mesh allocation failed."); throw DeadlyImportError("Invalid Quick3D-file, mesh allocation failed.");
} }
@ -237,7 +237,6 @@ void Q3DImporter::InternReadFile(const std::string &pFile,
if (minor > '0' && major == '3') if (minor > '0' && major == '3')
stream.IncPtr(mesh.faces.size()); stream.IncPtr(mesh.faces.size());
} }
// stream.IncPtr(4); // unknown value here
} break; } break;
// materials chunk // materials chunk
@ -275,8 +274,6 @@ void Q3DImporter::InternReadFile(const std::string &pFile,
// read the transparency // read the transparency
mat.transparency = stream.GetF4(); mat.transparency = stream.GetF4();
// unknown value here
// stream.IncPtr(4);
// FIX: it could be the texture index ... // FIX: it could be the texture index ...
mat.texIdx = (unsigned int)stream.GetI4(); mat.texIdx = (unsigned int)stream.GetI4();
} }
@ -425,7 +422,8 @@ outer:
pScene->mMeshes = new aiMesh *[pScene->mNumMaterials]; pScene->mMeshes = new aiMesh *[pScene->mNumMaterials];
for (unsigned int i = 0, real = 0; i < (unsigned int)materials.size(); ++i) { for (unsigned int i = 0, real = 0; i < (unsigned int)materials.size(); ++i) {
if (fidx[i].empty()) continue; if (fidx[i].empty())
continue;
// Allocate a mesh and a material // Allocate a mesh and a material
aiMesh *mesh = pScene->mMeshes[real] = new aiMesh(); aiMesh *mesh = pScene->mMeshes[real] = new aiMesh();
@ -548,14 +546,9 @@ outer:
// Now we need to attach the meshes to the root node of the scene // Now we need to attach the meshes to the root node of the scene
pScene->mRootNode->mNumMeshes = pScene->mNumMeshes; pScene->mRootNode->mNumMeshes = pScene->mNumMeshes;
pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes]; pScene->mRootNode->mMeshes = new unsigned int[pScene->mNumMeshes];
for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) for (unsigned int i = 0; i < pScene->mNumMeshes; ++i) {
pScene->mRootNode->mMeshes[i] = i; pScene->mRootNode->mMeshes[i] = i;
}
/*pScene->mRootNode->mTransformation *= aiMatrix4x4(
1.f, 0.f, 0.f, 0.f,
0.f, -1.f,0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, 0.f, 0.f, 1.f);*/
// Add cameras and light sources to the scene root node // Add cameras and light sources to the scene root node
pScene->mRootNode->mNumChildren = pScene->mNumLights + pScene->mNumCameras; pScene->mRootNode->mNumChildren = pScene->mNumLights + pScene->mNumCameras;
@ -577,4 +570,6 @@ outer:
} }
} }
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_Q3D_IMPORTER #endif // !! ASSIMP_BUILD_NO_Q3D_IMPORTER

View File

@ -55,9 +55,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <memory> #include <memory>
using namespace Assimp; namespace Assimp {
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Raw Importer", "Raw Importer",
"", "",
"", "",
@ -70,14 +70,6 @@ static const aiImporterDesc desc = {
"raw" "raw"
}; };
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
RAWImporter::RAWImporter() = default;
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
RAWImporter::~RAWImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool RAWImporter::CanRead(const std::string &filename, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { bool RAWImporter::CanRead(const std::string &filename, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
@ -295,4 +287,6 @@ void RAWImporter::InternReadFile(const std::string &pFile,
} }
} }
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_RAW_IMPORTER #endif // !! ASSIMP_BUILD_NO_RAW_IMPORTER

View File

@ -57,8 +57,8 @@ namespace Assimp {
*/ */
class RAWImporter : public BaseImporter { class RAWImporter : public BaseImporter {
public: public:
RAWImporter(); RAWImporter() = default;
~RAWImporter() override; ~RAWImporter() override = default;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.

View File

@ -69,9 +69,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <map> #include <map>
using namespace Assimp; namespace Assimp {
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Silo SIB Importer", "Silo SIB Importer",
"Richard Mitton (http://www.codersnotes.com/about)", "Richard Mitton (http://www.codersnotes.com/about)",
"", "",
@ -94,7 +94,7 @@ enum {
N N
}; };
typedef std::pair<uint32_t, uint32_t> SIBPair; using SIBPair = std::pair<uint32_t, uint32_t>;
struct SIBEdge { struct SIBEdge {
uint32_t faceA, faceB; uint32_t faceA, faceB;
@ -199,15 +199,6 @@ static aiString ReadString(StreamReaderLE *stream, uint32_t numWChars) {
return result; return result;
} }
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
SIBImporter::SIBImporter() = default;
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
SIBImporter::~SIBImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool SIBImporter::CanRead(const std::string &filename, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { bool SIBImporter::CanRead(const std::string &filename, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
@ -882,4 +873,6 @@ void SIBImporter::InternReadFile(const std::string &pFile,
} }
} }
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_SIB_IMPORTER #endif // !! ASSIMP_BUILD_NO_SIB_IMPORTER

View File

@ -57,8 +57,8 @@ namespace Assimp {
*/ */
class ASSIMP_API SIBImporter : public BaseImporter { class ASSIMP_API SIBImporter : public BaseImporter {
public: public:
SIBImporter(); SIBImporter() = default;
~SIBImporter() override; ~SIBImporter() override = default;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file. /** Returns whether the class can handle the format of the given file.

View File

@ -64,9 +64,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define strtok_s strtok_r #define strtok_s strtok_r
#endif #endif
using namespace Assimp; namespace Assimp {
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Valve SMD Importer", "Valve SMD Importer",
"", "",
"", "",
@ -1077,4 +1077,6 @@ void SMDImporter::ParseVertex(const char* szCurrent,
SMDI_PARSE_RETURN; SMDI_PARSE_RETURN;
} }
}
#endif // !! ASSIMP_BUILD_NO_SMD_IMPORTER #endif // !! ASSIMP_BUILD_NO_SMD_IMPORTER

View File

@ -52,11 +52,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <memory> #include <memory>
using namespace Assimp; namespace Assimp {
namespace { namespace {
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Stereolithography (STL) Importer", "Stereolithography (STL) Importer",
"", "",
"", "",
@ -129,7 +129,7 @@ STLImporter::STLImporter() :
mBuffer(), mBuffer(),
mFileSize(0), mFileSize(0),
mScene() { mScene() {
// empty // empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -250,13 +250,13 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
sz += 5; // skip the "solid" sz += 5; // skip the "solid"
SkipSpaces(&sz); SkipSpaces(&sz);
const char *szMe = sz; const char *szMe = sz;
while (!::IsSpaceOrNewLine(*sz)) { while (!IsSpaceOrNewLine(*sz)) {
sz++; sz++;
} }
size_t temp = (size_t)(sz - szMe); size_t temp = (size_t)(sz - szMe);
// setup the name of the node // setup the name of the node
if ( temp ) { if (temp) {
if (temp >= MAXLEN) { if (temp >= MAXLEN) {
throw DeadlyImportError("STL: Node name too long"); throw DeadlyImportError("STL: Node name too long");
} }
@ -303,7 +303,7 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
normalBuffer.emplace_back(vn); normalBuffer.emplace_back(vn);
normalBuffer.emplace_back(vn); normalBuffer.emplace_back(vn);
} }
} else if (!strncmp(sz, "vertex", 6) && ::IsSpaceOrNewLine(*(sz + 6))) { // vertex 1.50000 1.50000 0.00000 } else if (!strncmp(sz, "vertex", 6) && IsSpaceOrNewLine(*(sz + 6))) { // vertex 1.50000 1.50000 0.00000
if (faceVertexCounter >= 3) { if (faceVertexCounter >= 3) {
ASSIMP_LOG_ERROR("STL: a facet with more than 3 vertices has been found"); ASSIMP_LOG_ERROR("STL: a facet with more than 3 vertices has been found");
++sz; ++sz;
@ -325,14 +325,14 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
} else if (!::strncmp(sz, "endsolid", 8)) { } else if (!::strncmp(sz, "endsolid", 8)) {
do { do {
++sz; ++sz;
} while (!::IsLineEnd(*sz)); } while (!IsLineEnd(*sz));
SkipSpacesAndLineEnd(&sz); SkipSpacesAndLineEnd(&sz);
// finished! // finished!
break; break;
} else { // else skip the whole identifier } else { // else skip the whole identifier
do { do {
++sz; ++sz;
} while (!::IsSpaceOrNewLine(*sz)); } while (!IsSpaceOrNewLine(*sz));
} }
} }
@ -349,14 +349,14 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
throw DeadlyImportError("Normal buffer size does not match position buffer size"); throw DeadlyImportError("Normal buffer size does not match position buffer size");
} }
// only process positionbuffer when filled, else exception when accessing with index operator // only process position buffer when filled, else exception when accessing with index operator
// see line 353: only warning is triggered // see line 353: only warning is triggered
// see line 373(now): access to empty positionbuffer with index operator forced exception // see line 373(now): access to empty position buffer with index operator forced exception
if (!positionBuffer.empty()) { if (!positionBuffer.empty()) {
pMesh->mNumFaces = static_cast<unsigned int>(positionBuffer.size() / 3); pMesh->mNumFaces = static_cast<unsigned int>(positionBuffer.size() / 3);
pMesh->mNumVertices = static_cast<unsigned int>(positionBuffer.size()); pMesh->mNumVertices = static_cast<unsigned int>(positionBuffer.size());
pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
for (size_t i=0; i<pMesh->mNumVertices; ++i ) { for (size_t i = 0; i < pMesh->mNumVertices; ++i) {
pMesh->mVertices[i].x = positionBuffer[i].x; pMesh->mVertices[i].x = positionBuffer[i].x;
pMesh->mVertices[i].y = positionBuffer[i].y; pMesh->mVertices[i].y = positionBuffer[i].y;
pMesh->mVertices[i].z = positionBuffer[i].z; pMesh->mVertices[i].z = positionBuffer[i].z;
@ -366,7 +366,7 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
// also only process normalBuffer when filled, else exception when accessing with index operator // also only process normalBuffer when filled, else exception when accessing with index operator
if (!normalBuffer.empty()) { if (!normalBuffer.empty()) {
pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
for (size_t i=0; i<pMesh->mNumVertices; ++i ) { for (size_t i = 0; i < pMesh->mNumVertices; ++i) {
pMesh->mNormals[i].x = normalBuffer[i].x; pMesh->mNormals[i].x = normalBuffer[i].x;
pMesh->mNormals[i].y = normalBuffer[i].y; pMesh->mNormals[i].y = normalBuffer[i].y;
pMesh->mNormals[i].z = normalBuffer[i].z; pMesh->mNormals[i].z = normalBuffer[i].z;
@ -450,9 +450,8 @@ bool STLImporter::LoadBinaryFile() {
aiVector3D *vp = pMesh->mVertices = new aiVector3D[pMesh->mNumVertices]; aiVector3D *vp = pMesh->mVertices = new aiVector3D[pMesh->mNumVertices];
aiVector3D *vn = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices]; aiVector3D *vn = pMesh->mNormals = new aiVector3D[pMesh->mNumVertices];
typedef aiVector3t<float> aiVector3F; aiVector3f *theVec;
aiVector3F *theVec; aiVector3f theVec3F;
aiVector3F theVec3F;
for (unsigned int i = 0; i < pMesh->mNumFaces; ++i) { for (unsigned int i = 0; i < pMesh->mNumFaces; ++i) {
// NOTE: Blender sometimes writes empty normals ... this is not // NOTE: Blender sometimes writes empty normals ... this is not
@ -460,8 +459,8 @@ bool STLImporter::LoadBinaryFile() {
// There's one normal for the face in the STL; use it three times // There's one normal for the face in the STL; use it three times
// for vertex normals // for vertex normals
theVec = (aiVector3F *)sz; theVec = (aiVector3f *)sz;
::memcpy(&theVec3F, theVec, sizeof(aiVector3F)); ::memcpy(&theVec3F, theVec, sizeof(aiVector3f));
vn->x = theVec3F.x; vn->x = theVec3F.x;
vn->y = theVec3F.y; vn->y = theVec3F.y;
vn->z = theVec3F.z; vn->z = theVec3F.z;
@ -471,7 +470,7 @@ bool STLImporter::LoadBinaryFile() {
vn += 3; vn += 3;
// vertex 1 // vertex 1
::memcpy(&theVec3F, theVec, sizeof(aiVector3F)); ::memcpy(&theVec3F, theVec, sizeof(aiVector3f));
vp->x = theVec3F.x; vp->x = theVec3F.x;
vp->y = theVec3F.y; vp->y = theVec3F.y;
vp->z = theVec3F.z; vp->z = theVec3F.z;
@ -479,7 +478,7 @@ bool STLImporter::LoadBinaryFile() {
++vp; ++vp;
// vertex 2 // vertex 2
::memcpy(&theVec3F, theVec, sizeof(aiVector3F)); ::memcpy(&theVec3F, theVec, sizeof(aiVector3f));
vp->x = theVec3F.x; vp->x = theVec3F.x;
vp->y = theVec3F.y; vp->y = theVec3F.y;
vp->z = theVec3F.z; vp->z = theVec3F.z;
@ -487,7 +486,7 @@ bool STLImporter::LoadBinaryFile() {
++vp; ++vp;
// vertex 3 // vertex 3
::memcpy(&theVec3F, theVec, sizeof(aiVector3F)); ::memcpy(&theVec3F, theVec, sizeof(aiVector3f));
vp->x = theVec3F.x; vp->x = theVec3F.x;
vp->y = theVec3F.y; vp->y = theVec3F.y;
vp->z = theVec3F.z; vp->z = theVec3F.z;
@ -570,4 +569,6 @@ void STLImporter::pushMeshesToNode(std::vector<unsigned int> &meshIndices, aiNod
meshIndices.clear(); meshIndices.clear();
} }
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_STL_IMPORTER #endif // !! ASSIMP_BUILD_NO_STL_IMPORTER

View File

@ -51,9 +51,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/Importer.hpp> #include <assimp/Importer.hpp>
using namespace Assimp; namespace Assimp {
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Terragen Heightmap Importer", "Terragen Heightmap Importer",
"", "",
"", "",
@ -73,10 +73,6 @@ TerragenImporter::TerragenImporter() :
// empty // empty
} }
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
TerragenImporter::~TerragenImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool TerragenImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { bool TerragenImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
@ -244,4 +240,6 @@ void TerragenImporter::InternReadFile(const std::string &pFile,
pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN; pScene->mFlags |= AI_SCENE_FLAGS_TERRAIN;
} }
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_TERRAGEN_IMPORTER #endif // !! ASSIMP_BUILD_NO_TERRAGEN_IMPORTER

View File

@ -73,7 +73,7 @@ namespace Assimp {
class TerragenImporter : public BaseImporter { class TerragenImporter : public BaseImporter {
public: public:
TerragenImporter(); TerragenImporter();
~TerragenImporter() override; ~TerragenImporter() override = default;
// ------------------------------------------------------------------- // -------------------------------------------------------------------
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool CanRead(const std::string &pFile, IOSystem *pIOHandler,

View File

@ -63,7 +63,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cstdint> #include <cstdint>
#include <memory> #include <memory>
using namespace Assimp; namespace Assimp {
namespace Unreal { namespace Unreal {
@ -152,7 +152,7 @@ inline void DecompressVertex(aiVector3D &v, int32_t in) {
} // end namespace Unreal } // end namespace Unreal
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Unreal Mesh Importer", "Unreal Mesh Importer",
"", "",
"", "",
@ -178,7 +178,7 @@ UnrealImporter::~UnrealImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool UnrealImporter::CanRead(const std::string & filename, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const { bool UnrealImporter::CanRead(const std::string &filename, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
return SimpleExtensionCheck(filename, "3d", "uc"); return SimpleExtensionCheck(filename, "3d", "uc");
} }
@ -336,12 +336,12 @@ void UnrealImporter::InternReadFile(const std::string &pFile,
tempTextures.emplace_back(); tempTextures.emplace_back();
std::pair<std::string, std::string> &me = tempTextures.back(); std::pair<std::string, std::string> &me = tempTextures.back();
for (; !IsLineEnd(*data); ++data) { for (; !IsLineEnd(*data); ++data) {
if (!::ASSIMP_strincmp(data, "NAME=", 5)) { if (!ASSIMP_strincmp(data, "NAME=", 5)) {
const char *d = data += 5; const char *d = data += 5;
for (; !IsSpaceOrNewLine(*data); ++data) for (; !IsSpaceOrNewLine(*data); ++data)
; ;
me.first = std::string(d, (size_t)(data - d)); me.first = std::string(d, (size_t)(data - d));
} else if (!::ASSIMP_strincmp(data, "FILE=", 5)) { } else if (!ASSIMP_strincmp(data, "FILE=", 5)) {
const char *d = data += 5; const char *d = data += 5;
for (; !IsSpaceOrNewLine(*data); ++data) for (; !IsSpaceOrNewLine(*data); ++data)
; ;
@ -363,10 +363,10 @@ void UnrealImporter::InternReadFile(const std::string &pFile,
std::pair<unsigned int, std::string> &me = textures.back(); std::pair<unsigned int, std::string> &me = textures.back();
for (; !IsLineEnd(*data); ++data) { for (; !IsLineEnd(*data); ++data) {
if (!::ASSIMP_strincmp(data, "NUM=", 4)) { if (!ASSIMP_strincmp(data, "NUM=", 4)) {
data += 4; data += 4;
me.first = strtoul10(data, &data); me.first = strtoul10(data, &data);
} else if (!::ASSIMP_strincmp(data, "TEXTURE=", 8)) { } else if (!ASSIMP_strincmp(data, "TEXTURE=", 8)) {
data += 8; data += 8;
const char *d = data; const char *d = data;
for (; !IsSpaceOrNewLine(*data); ++data) for (; !IsSpaceOrNewLine(*data); ++data)
@ -516,4 +516,6 @@ void UnrealImporter::InternReadFile(const std::string &pFile,
flipper.Execute(pScene); flipper.Execute(pScene);
} }
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_3D_IMPORTER #endif // !! ASSIMP_BUILD_NO_3D_IMPORTER

View File

@ -57,10 +57,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cctype> #include <cctype>
#include <memory> #include <memory>
using namespace Assimp; namespace Assimp {
using namespace Assimp::Formatter; using namespace Assimp::Formatter;
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"Direct3D XFile Importer", "Direct3D XFile Importer",
"", "",
"", "",
@ -73,142 +74,137 @@ static const aiImporterDesc desc = {
"x" "x"
}; };
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
XFileImporter::XFileImporter() = default;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file. // Returns whether the class can handle the format of the given file.
bool XFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const { bool XFileImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const uint32_t token[] = { AI_MAKE_MAGIC("xof ") }; static const uint32_t token[] = { AI_MAKE_MAGIC("xof ") };
return CheckMagicToken(pIOHandler,pFile,token,AI_COUNT_OF(token)); return CheckMagicToken(pIOHandler, pFile, token, AI_COUNT_OF(token));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Get file extension list // Get file extension list
const aiImporterDesc* XFileImporter::GetInfo () const { const aiImporterDesc *XFileImporter::GetInfo() const {
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void XFileImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler) { void XFileImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
// read file into memory // read file into memory
std::unique_ptr<IOStream> file( pIOHandler->Open( pFile)); std::unique_ptr<IOStream> file(pIOHandler->Open(pFile));
if (file == nullptr) { if (file == nullptr) {
throw DeadlyImportError( "Failed to open file ", pFile, "." ); throw DeadlyImportError("Failed to open file ", pFile, ".");
} }
static const size_t MinSize = 16; static const size_t MinSize = 16;
size_t fileSize = file->FileSize(); size_t fileSize = file->FileSize();
if ( fileSize < MinSize ) { if (fileSize < MinSize) {
throw DeadlyImportError( "XFile is too small." ); throw DeadlyImportError("XFile is too small.");
} }
// in the hope that binary files will never start with a BOM ... // in the hope that binary files will never start with a BOM ...
mBuffer.resize( fileSize + 1); mBuffer.resize(fileSize + 1);
file->Read( &mBuffer.front(), 1, fileSize); file->Read(&mBuffer.front(), 1, fileSize);
ConvertToUTF8(mBuffer); ConvertToUTF8(mBuffer);
// parse the file into a temporary representation // parse the file into a temporary representation
XFileParser parser( mBuffer); XFileParser parser(mBuffer);
// and create the proper return structures out of it // and create the proper return structures out of it
CreateDataRepresentationFromImport( pScene, parser.GetImportedData()); CreateDataRepresentationFromImport(pScene, parser.GetImportedData());
// if nothing came from it, report it as error // if nothing came from it, report it as error
if ( !pScene->mRootNode ) { if (!pScene->mRootNode) {
throw DeadlyImportError( "XFile is ill-formatted - no content imported." ); throw DeadlyImportError("XFile is ill-formatted - no content imported.");
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructs the return data structure out of the imported data. // Constructs the return data structure out of the imported data.
void XFileImporter::CreateDataRepresentationFromImport( aiScene* pScene, XFile::Scene* pData) void XFileImporter::CreateDataRepresentationFromImport(aiScene *pScene, XFile::Scene *pData) {
{
// Read the global materials first so that meshes referring to them can find them later // Read the global materials first so that meshes referring to them can find them later
ConvertMaterials( pScene, pData->mGlobalMaterials); ConvertMaterials(pScene, pData->mGlobalMaterials);
// copy nodes, extracting meshes and materials on the way // copy nodes, extracting meshes and materials on the way
pScene->mRootNode = CreateNodes( pScene, nullptr, pData->mRootNode); pScene->mRootNode = CreateNodes(pScene, nullptr, pData->mRootNode);
// extract animations // extract animations
CreateAnimations( pScene, pData); CreateAnimations(pScene, pData);
// read the global meshes that were stored outside of any node // read the global meshes that were stored outside of any node
if( !pData->mGlobalMeshes.empty() ) { if (!pData->mGlobalMeshes.empty()) {
// create a root node to hold them if there isn't any, yet // create a root node to hold them if there isn't any, yet
if( pScene->mRootNode == nullptr ) { if (pScene->mRootNode == nullptr) {
pScene->mRootNode = new aiNode; pScene->mRootNode = new aiNode;
pScene->mRootNode->mName.Set( "$dummy_node"); pScene->mRootNode->mName.Set("$dummy_node");
} }
// convert all global meshes and store them in the root node. // convert all global meshes and store them in the root node.
// If there was one before, the global meshes now suddenly have its transformation matrix... // If there was one before, the global meshes now suddenly have its transformation matrix...
// Don't know what to do there, I don't want to insert another node under the present root node // Don't know what to do there, I don't want to insert another node under the present root node
// just to avoid this. // just to avoid this.
CreateMeshes( pScene, pScene->mRootNode, pData->mGlobalMeshes); CreateMeshes(pScene, pScene->mRootNode, pData->mGlobalMeshes);
} }
if (!pScene->mRootNode) { if (!pScene->mRootNode) {
throw DeadlyImportError( "No root node" ); throw DeadlyImportError("No root node");
} }
// Convert everything to OpenGL space... it's the same operation as the conversion back, so we can reuse the step directly // Convert everything to OpenGL space... it's the same operation as the conversion back, so we can reuse the step directly
MakeLeftHandedProcess convertProcess; MakeLeftHandedProcess convertProcess;
convertProcess.Execute( pScene); convertProcess.Execute(pScene);
FlipWindingOrderProcess flipper; FlipWindingOrderProcess flipper;
flipper.Execute(pScene); flipper.Execute(pScene);
// finally: create a dummy material if not material was imported // finally: create a dummy material if not material was imported
if( pScene->mNumMaterials == 0) { if (pScene->mNumMaterials == 0) {
pScene->mNumMaterials = 1; pScene->mNumMaterials = 1;
// create the Material // create the Material
aiMaterial* mat = new aiMaterial; aiMaterial *mat = new aiMaterial;
int shadeMode = (int) aiShadingMode_Gouraud; int shadeMode = (int)aiShadingMode_Gouraud;
mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL); mat->AddProperty<int>(&shadeMode, 1, AI_MATKEY_SHADING_MODEL);
// material colours // material colours
int specExp = 1; int specExp = 1;
aiColor3D clr = aiColor3D( 0, 0, 0); aiColor3D clr = aiColor3D(0, 0, 0);
mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_EMISSIVE); mat->AddProperty(&clr, 1, AI_MATKEY_COLOR_EMISSIVE);
mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_SPECULAR); mat->AddProperty(&clr, 1, AI_MATKEY_COLOR_SPECULAR);
clr = aiColor3D( 0.5f, 0.5f, 0.5f); clr = aiColor3D(0.5f, 0.5f, 0.5f);
mat->AddProperty( &clr, 1, AI_MATKEY_COLOR_DIFFUSE); mat->AddProperty(&clr, 1, AI_MATKEY_COLOR_DIFFUSE);
mat->AddProperty( &specExp, 1, AI_MATKEY_SHININESS); mat->AddProperty(&specExp, 1, AI_MATKEY_SHININESS);
pScene->mMaterials = new aiMaterial*[1]; pScene->mMaterials = new aiMaterial *[1];
pScene->mMaterials[0] = mat; pScene->mMaterials[0] = mat;
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Recursively creates scene nodes from the imported hierarchy. // Recursively creates scene nodes from the imported hierarchy.
aiNode* XFileImporter::CreateNodes( aiScene* pScene, aiNode* pParent, const XFile::Node* pNode) { aiNode *XFileImporter::CreateNodes(aiScene *pScene, aiNode *pParent, const XFile::Node *pNode) {
if ( !pNode ) { if (!pNode) {
return nullptr; return nullptr;
} }
// create node // create node
aiNode* node = new aiNode; aiNode *node = new aiNode;
node->mName.length = (ai_uint32)pNode->mName.length(); node->mName.length = (ai_uint32)pNode->mName.length();
node->mParent = pParent; node->mParent = pParent;
memcpy( node->mName.data, pNode->mName.c_str(), pNode->mName.length()); memcpy(node->mName.data, pNode->mName.c_str(), pNode->mName.length());
node->mName.data[node->mName.length] = 0; node->mName.data[node->mName.length] = 0;
node->mTransformation = pNode->mTrafoMatrix; node->mTransformation = pNode->mTrafoMatrix;
// convert meshes from the source node // convert meshes from the source node
CreateMeshes( pScene, node, pNode->mMeshes); CreateMeshes(pScene, node, pNode->mMeshes);
// handle children // handle children
if( !pNode->mChildren.empty() ) { if (!pNode->mChildren.empty()) {
node->mNumChildren = (unsigned int)pNode->mChildren.size(); node->mNumChildren = (unsigned int)pNode->mChildren.size();
node->mChildren = new aiNode* [node->mNumChildren]; node->mChildren = new aiNode *[node->mNumChildren];
for ( unsigned int a = 0; a < pNode->mChildren.size(); ++a ) { for (unsigned int a = 0; a < pNode->mChildren.size(); ++a) {
node->mChildren[ a ] = CreateNodes( pScene, node, pNode->mChildren[ a ] ); node->mChildren[a] = CreateNodes(pScene, node, pNode->mChildren[a]);
} }
} }
@ -217,55 +213,55 @@ aiNode* XFileImporter::CreateNodes( aiScene* pScene, aiNode* pParent, const XFil
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Creates the meshes for the given node. // Creates the meshes for the given node.
void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vector<XFile::Mesh*>& pMeshes) { void XFileImporter::CreateMeshes(aiScene *pScene, aiNode *pNode, const std::vector<XFile::Mesh *> &pMeshes) {
if (pMeshes.empty()) { if (pMeshes.empty()) {
return; return;
} }
// create a mesh for each mesh-material combination in the source node // create a mesh for each mesh-material combination in the source node
std::vector<aiMesh*> meshes; std::vector<aiMesh *> meshes;
for( unsigned int a = 0; a < pMeshes.size(); ++a ) { for (unsigned int a = 0; a < pMeshes.size(); ++a) {
XFile::Mesh* sourceMesh = pMeshes[a]; XFile::Mesh *sourceMesh = pMeshes[a];
if ( nullptr == sourceMesh ) { if (nullptr == sourceMesh) {
continue; continue;
} }
// first convert its materials so that we can find them with their index afterwards // first convert its materials so that we can find them with their index afterwards
ConvertMaterials( pScene, sourceMesh->mMaterials); ConvertMaterials(pScene, sourceMesh->mMaterials);
unsigned int numMaterials = std::max( (unsigned int)sourceMesh->mMaterials.size(), 1u); unsigned int numMaterials = std::max((unsigned int)sourceMesh->mMaterials.size(), 1u);
for( unsigned int b = 0; b < numMaterials; ++b ) { for (unsigned int b = 0; b < numMaterials; ++b) {
// collect the faces belonging to this material // collect the faces belonging to this material
std::vector<unsigned int> faces; std::vector<unsigned int> faces;
unsigned int numVertices = 0; unsigned int numVertices = 0;
if( !sourceMesh->mFaceMaterials.empty() ) { if (!sourceMesh->mFaceMaterials.empty()) {
// if there is a per-face material defined, select the faces with the corresponding material // if there is a per-face material defined, select the faces with the corresponding material
for( unsigned int c = 0; c < sourceMesh->mFaceMaterials.size(); ++c ) { for (unsigned int c = 0; c < sourceMesh->mFaceMaterials.size(); ++c) {
if( sourceMesh->mFaceMaterials[c] == b) { if (sourceMesh->mFaceMaterials[c] == b) {
faces.push_back( c); faces.push_back(c);
numVertices += (unsigned int)sourceMesh->mPosFaces[c].mIndices.size(); numVertices += (unsigned int)sourceMesh->mPosFaces[c].mIndices.size();
} }
} }
} else { } else {
// if there is no per-face material, place everything into one mesh // if there is no per-face material, place everything into one mesh
for( unsigned int c = 0; c < sourceMesh->mPosFaces.size(); ++c ) { for (unsigned int c = 0; c < sourceMesh->mPosFaces.size(); ++c) {
faces.push_back( c); faces.push_back(c);
numVertices += (unsigned int)sourceMesh->mPosFaces[c].mIndices.size(); numVertices += (unsigned int)sourceMesh->mPosFaces[c].mIndices.size();
} }
} }
// no faces/vertices using this material? strange... // no faces/vertices using this material? strange...
if ( numVertices == 0 ) { if (numVertices == 0) {
continue; continue;
} }
// create a submesh using this material // create a submesh using this material
aiMesh* mesh = new aiMesh; aiMesh *mesh = new aiMesh;
meshes.push_back( mesh); meshes.push_back(mesh);
// find the material in the scene's material list. Either own material // find the material in the scene's material list. Either own material
// or referenced material, it should already have a valid index // or referenced material, it should already have a valid index
if( !sourceMesh->mFaceMaterials.empty() ) { if (!sourceMesh->mFaceMaterials.empty()) {
mesh->mMaterialIndex = static_cast<unsigned int>(sourceMesh->mMaterials[b].sceneIndex); mesh->mMaterialIndex = static_cast<unsigned int>(sourceMesh->mMaterials[b].sceneIndex);
} else { } else {
mesh->mMaterialIndex = 0; mesh->mMaterialIndex = 0;
@ -282,41 +278,41 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
mesh->mName.Set(sourceMesh->mName); mesh->mName.Set(sourceMesh->mName);
// normals? // normals?
if ( sourceMesh->mNormals.size() > 0 ) { if (sourceMesh->mNormals.size() > 0) {
mesh->mNormals = new aiVector3D[ numVertices ]; mesh->mNormals = new aiVector3D[numVertices];
} }
// texture coords // texture coords
for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c ) { for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++c) {
if ( !sourceMesh->mTexCoords[ c ].empty() ) { if (!sourceMesh->mTexCoords[c].empty()) {
mesh->mTextureCoords[ c ] = new aiVector3D[ numVertices ]; mesh->mTextureCoords[c] = new aiVector3D[numVertices];
} }
} }
// vertex colors // vertex colors
for( unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c ) { for (unsigned int c = 0; c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c) {
if ( !sourceMesh->mColors[ c ].empty() ) { if (!sourceMesh->mColors[c].empty()) {
mesh->mColors[ c ] = new aiColor4D[ numVertices ]; mesh->mColors[c] = new aiColor4D[numVertices];
} }
} }
// now collect the vertex data of all data streams present in the imported mesh // now collect the vertex data of all data streams present in the imported mesh
unsigned int newIndex( 0 ); unsigned int newIndex(0);
std::vector<unsigned int> orgPoints; // from which original point each new vertex stems std::vector<unsigned int> orgPoints; // from which original point each new vertex stems
orgPoints.resize( numVertices, 0); orgPoints.resize(numVertices, 0);
for( unsigned int c = 0; c < faces.size(); ++c ) { for (unsigned int c = 0; c < faces.size(); ++c) {
unsigned int f = faces[c]; // index of the source face unsigned int f = faces[c]; // index of the source face
const XFile::Face& pf = sourceMesh->mPosFaces[f]; // position source face const XFile::Face &pf = sourceMesh->mPosFaces[f]; // position source face
// create face. either triangle or triangle fan depending on the index count // create face. either triangle or triangle fan depending on the index count
aiFace& df = mesh->mFaces[c]; // destination face aiFace &df = mesh->mFaces[c]; // destination face
df.mNumIndices = (unsigned int)pf.mIndices.size(); df.mNumIndices = (unsigned int)pf.mIndices.size();
df.mIndices = new unsigned int[ df.mNumIndices]; df.mIndices = new unsigned int[df.mNumIndices];
// collect vertex data for indices of this face // collect vertex data for indices of this face
for( unsigned int d = 0; d < df.mNumIndices; ++d ) { for (unsigned int d = 0; d < df.mNumIndices; ++d) {
df.mIndices[ d ] = newIndex; df.mIndices[d] = newIndex;
const unsigned int newIdx( pf.mIndices[ d ] ); const unsigned int newIdx = pf.mIndices[d];
if ( newIdx > sourceMesh->mPositions.size() ) { if (newIdx >= sourceMesh->mPositions.size()) {
continue; continue;
} }
@ -325,24 +321,26 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
// Position // Position
mesh->mVertices[newIndex] = sourceMesh->mPositions[pf.mIndices[d]]; mesh->mVertices[newIndex] = sourceMesh->mPositions[pf.mIndices[d]];
// Normal, if present // Normal, if present
if ( mesh->HasNormals() ) { if (mesh->HasNormals()) {
if ( sourceMesh->mNormFaces[ f ].mIndices.size() > d ) { if (sourceMesh->mNormFaces[f].mIndices.size() > d) {
const size_t idx( sourceMesh->mNormFaces[ f ].mIndices[ d ] ); const size_t idx(sourceMesh->mNormFaces[f].mIndices[d]);
mesh->mNormals[ newIndex ] = sourceMesh->mNormals[ idx ]; if (idx < sourceMesh->mNormals.size()) {
mesh->mNormals[newIndex] = sourceMesh->mNormals[idx];
}
} }
} }
// texture coord sets // texture coord sets
for( unsigned int e = 0; e < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++e ) { for (unsigned int e = 0; e < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++e) {
if( mesh->HasTextureCoords( e)) { if (mesh->HasTextureCoords(e)) {
aiVector2D tex = sourceMesh->mTexCoords[e][pf.mIndices[d]]; aiVector2D tex = sourceMesh->mTexCoords[e][pf.mIndices[d]];
mesh->mTextureCoords[e][newIndex] = aiVector3D( tex.x, 1.0f - tex.y, 0.0f); mesh->mTextureCoords[e][newIndex] = aiVector3D(tex.x, 1.0f - tex.y, 0.0f);
} }
} }
// vertex color sets // vertex color sets
for ( unsigned int e = 0; e < AI_MAX_NUMBER_OF_COLOR_SETS; ++e ) { for (unsigned int e = 0; e < AI_MAX_NUMBER_OF_COLOR_SETS; ++e) {
if ( mesh->HasVertexColors( e ) ) { if (mesh->HasVertexColors(e)) {
mesh->mColors[ e ][ newIndex ] = sourceMesh->mColors[ e ][ pf.mIndices[ d ] ]; mesh->mColors[e][newIndex] = sourceMesh->mColors[e][pf.mIndices[d]];
} }
} }
@ -351,63 +349,66 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
} }
// there should be as much new vertices as we calculated before // there should be as much new vertices as we calculated before
ai_assert( newIndex == numVertices); ai_assert(newIndex == numVertices);
// convert all bones of the source mesh which influence vertices in this newly created mesh // convert all bones of the source mesh which influence vertices in this newly created mesh
const std::vector<XFile::Bone>& bones = sourceMesh->mBones; const std::vector<XFile::Bone> &bones = sourceMesh->mBones;
std::vector<aiBone*> newBones; std::vector<aiBone *> newBones;
for( unsigned int c = 0; c < bones.size(); ++c ) { for (unsigned int c = 0; c < bones.size(); ++c) {
const XFile::Bone& obone = bones[c]; const XFile::Bone &obone = bones[c];
// set up a vertex-linear array of the weights for quick searching if a bone influences a vertex // set up a vertex-linear array of the weights for quick searching if a bone influences a vertex
std::vector<ai_real> oldWeights( sourceMesh->mPositions.size(), 0.0); std::vector<ai_real> oldWeights(sourceMesh->mPositions.size(), 0.0);
for ( unsigned int d = 0; d < obone.mWeights.size(); ++d ) { for (unsigned int d = 0; d < obone.mWeights.size(); ++d) {
oldWeights[ obone.mWeights[ d ].mVertex ] = obone.mWeights[ d ].mWeight; const unsigned int boneIdx = obone.mWeights[d].mVertex;
if (boneIdx < obone.mWeights.size()) {
oldWeights[obone.mWeights[d].mVertex] = obone.mWeights[d].mWeight;
}
} }
// collect all vertex weights that influence a vertex in the new mesh // collect all vertex weights that influence a vertex in the new mesh
std::vector<aiVertexWeight> newWeights; std::vector<aiVertexWeight> newWeights;
newWeights.reserve( numVertices); newWeights.reserve(numVertices);
for( unsigned int d = 0; d < orgPoints.size(); ++d ) { for (unsigned int d = 0; d < orgPoints.size(); ++d) {
// does the new vertex stem from an old vertex which was influenced by this bone? // does the new vertex stem from an old vertex which was influenced by this bone?
ai_real w = oldWeights[orgPoints[d]]; ai_real w = oldWeights[orgPoints[d]];
if ( w > 0.0 ) { if (w > 0.0) {
newWeights.emplace_back( d, w ); newWeights.emplace_back(d, w);
} }
} }
// if the bone has no weights in the newly created mesh, ignore it // if the bone has no weights in the newly created mesh, ignore it
if ( newWeights.empty() ) { if (newWeights.empty()) {
continue; continue;
} }
// create // create
aiBone* nbone = new aiBone; aiBone *nbone = new aiBone;
newBones.push_back( nbone); newBones.push_back(nbone);
// copy name and matrix // copy name and matrix
nbone->mName.Set( obone.mName); nbone->mName.Set(obone.mName);
nbone->mOffsetMatrix = obone.mOffsetMatrix; nbone->mOffsetMatrix = obone.mOffsetMatrix;
nbone->mNumWeights = (unsigned int)newWeights.size(); nbone->mNumWeights = (unsigned int)newWeights.size();
nbone->mWeights = new aiVertexWeight[nbone->mNumWeights]; nbone->mWeights = new aiVertexWeight[nbone->mNumWeights];
for ( unsigned int d = 0; d < newWeights.size(); ++d ) { for (unsigned int d = 0; d < newWeights.size(); ++d) {
nbone->mWeights[ d ] = newWeights[ d ]; nbone->mWeights[d] = newWeights[d];
} }
} }
// store the bones in the mesh // store the bones in the mesh
mesh->mNumBones = (unsigned int)newBones.size(); mesh->mNumBones = (unsigned int)newBones.size();
if( !newBones.empty()) { if (!newBones.empty()) {
mesh->mBones = new aiBone*[mesh->mNumBones]; mesh->mBones = new aiBone *[mesh->mNumBones];
std::copy( newBones.begin(), newBones.end(), mesh->mBones); std::copy(newBones.begin(), newBones.end(), mesh->mBones);
} }
} }
} }
// reallocate scene mesh array to be large enough // reallocate scene mesh array to be large enough
aiMesh** prevArray = pScene->mMeshes; aiMesh **prevArray = pScene->mMeshes;
pScene->mMeshes = new aiMesh*[pScene->mNumMeshes + meshes.size()]; pScene->mMeshes = new aiMesh *[pScene->mNumMeshes + meshes.size()];
if( prevArray) { if (prevArray) {
memcpy( pScene->mMeshes, prevArray, pScene->mNumMeshes * sizeof( aiMesh*)); memcpy(pScene->mMeshes, prevArray, pScene->mNumMeshes * sizeof(aiMesh *));
delete [] prevArray; delete[] prevArray;
} }
// allocate mesh index array in the node // allocate mesh index array in the node
@ -415,7 +416,7 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
pNode->mMeshes = new unsigned int[pNode->mNumMeshes]; pNode->mMeshes = new unsigned int[pNode->mNumMeshes];
// store all meshes in the mesh library of the scene and store their indices in the node // store all meshes in the mesh library of the scene and store their indices in the node
for( unsigned int a = 0; a < meshes.size(); a++) { for (unsigned int a = 0; a < meshes.size(); a++) {
pScene->mMeshes[pScene->mNumMeshes] = meshes[a]; pScene->mMeshes[pScene->mNumMeshes] = meshes[a];
pNode->mMeshes[a] = pScene->mNumMeshes; pNode->mMeshes[a] = pScene->mNumMeshes;
pScene->mNumMeshes++; pScene->mNumMeshes++;
@ -424,35 +425,34 @@ void XFileImporter::CreateMeshes( aiScene* pScene, aiNode* pNode, const std::vec
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Converts the animations from the given imported data and creates them in the scene. // Converts the animations from the given imported data and creates them in the scene.
void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData) { void XFileImporter::CreateAnimations(aiScene *pScene, const XFile::Scene *pData) {
std::vector<aiAnimation*> newAnims; std::vector<aiAnimation *> newAnims;
for( unsigned int a = 0; a < pData->mAnims.size(); ++a ) { for (unsigned int a = 0; a < pData->mAnims.size(); ++a) {
const XFile::Animation* anim = pData->mAnims[a]; const XFile::Animation *anim = pData->mAnims[a];
// some exporters mock me with empty animation tags. // some exporters mock me with empty animation tags.
if ( anim->mAnims.empty() ) { if (anim->mAnims.empty()) {
continue; continue;
} }
// create a new animation to hold the data // create a new animation to hold the data
aiAnimation* nanim = new aiAnimation; aiAnimation *nanim = new aiAnimation;
newAnims.push_back( nanim); newAnims.push_back(nanim);
nanim->mName.Set( anim->mName); nanim->mName.Set(anim->mName);
// duration will be determined by the maximum length // duration will be determined by the maximum length
nanim->mDuration = 0; nanim->mDuration = 0;
nanim->mTicksPerSecond = pData->mAnimTicksPerSecond; nanim->mTicksPerSecond = pData->mAnimTicksPerSecond;
nanim->mNumChannels = (unsigned int)anim->mAnims.size(); nanim->mNumChannels = (unsigned int)anim->mAnims.size();
nanim->mChannels = new aiNodeAnim*[nanim->mNumChannels]; nanim->mChannels = new aiNodeAnim *[nanim->mNumChannels];
for( unsigned int b = 0; b < anim->mAnims.size(); ++b ) { for (unsigned int b = 0; b < anim->mAnims.size(); ++b) {
const XFile::AnimBone* bone = anim->mAnims[b]; const XFile::AnimBone *bone = anim->mAnims[b];
aiNodeAnim* nbone = new aiNodeAnim; aiNodeAnim *nbone = new aiNodeAnim;
nbone->mNodeName.Set( bone->mBoneName); nbone->mNodeName.Set(bone->mBoneName);
nanim->mChannels[b] = nbone; nanim->mChannels[b] = nbone;
// key-frames are given as combined transformation matrix keys // key-frames are given as combined transformation matrix keys
if( !bone->mTrafoKeys.empty() ) if (!bone->mTrafoKeys.empty()) {
{
nbone->mNumPositionKeys = (unsigned int)bone->mTrafoKeys.size(); nbone->mNumPositionKeys = (unsigned int)bone->mTrafoKeys.size();
nbone->mPositionKeys = new aiVectorKey[nbone->mNumPositionKeys]; nbone->mPositionKeys = new aiVectorKey[nbone->mNumPositionKeys];
nbone->mNumRotationKeys = (unsigned int)bone->mTrafoKeys.size(); nbone->mNumRotationKeys = (unsigned int)bone->mTrafoKeys.size();
@ -460,44 +460,44 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData
nbone->mNumScalingKeys = (unsigned int)bone->mTrafoKeys.size(); nbone->mNumScalingKeys = (unsigned int)bone->mTrafoKeys.size();
nbone->mScalingKeys = new aiVectorKey[nbone->mNumScalingKeys]; nbone->mScalingKeys = new aiVectorKey[nbone->mNumScalingKeys];
for( unsigned int c = 0; c < bone->mTrafoKeys.size(); ++c) { for (unsigned int c = 0; c < bone->mTrafoKeys.size(); ++c) {
// deconstruct each matrix into separate position, rotation and scaling // deconstruct each matrix into separate position, rotation and scaling
double time = bone->mTrafoKeys[c].mTime; double time = bone->mTrafoKeys[c].mTime;
aiMatrix4x4 trafo = bone->mTrafoKeys[c].mMatrix; aiMatrix4x4 trafo = bone->mTrafoKeys[c].mMatrix;
// extract position // extract position
aiVector3D pos( trafo.a4, trafo.b4, trafo.c4); aiVector3D pos(trafo.a4, trafo.b4, trafo.c4);
nbone->mPositionKeys[c].mTime = time; nbone->mPositionKeys[c].mTime = time;
nbone->mPositionKeys[c].mValue = pos; nbone->mPositionKeys[c].mValue = pos;
// extract scaling // extract scaling
aiVector3D scale; aiVector3D scale;
scale.x = aiVector3D( trafo.a1, trafo.b1, trafo.c1).Length(); scale.x = aiVector3D(trafo.a1, trafo.b1, trafo.c1).Length();
scale.y = aiVector3D( trafo.a2, trafo.b2, trafo.c2).Length(); scale.y = aiVector3D(trafo.a2, trafo.b2, trafo.c2).Length();
scale.z = aiVector3D( trafo.a3, trafo.b3, trafo.c3).Length(); scale.z = aiVector3D(trafo.a3, trafo.b3, trafo.c3).Length();
nbone->mScalingKeys[c].mTime = time; nbone->mScalingKeys[c].mTime = time;
nbone->mScalingKeys[c].mValue = scale; nbone->mScalingKeys[c].mValue = scale;
// reconstruct rotation matrix without scaling // reconstruct rotation matrix without scaling
aiMatrix3x3 rotmat( aiMatrix3x3 rotmat(
trafo.a1 / scale.x, trafo.a2 / scale.y, trafo.a3 / scale.z, trafo.a1 / scale.x, trafo.a2 / scale.y, trafo.a3 / scale.z,
trafo.b1 / scale.x, trafo.b2 / scale.y, trafo.b3 / scale.z, trafo.b1 / scale.x, trafo.b2 / scale.y, trafo.b3 / scale.z,
trafo.c1 / scale.x, trafo.c2 / scale.y, trafo.c3 / scale.z); trafo.c1 / scale.x, trafo.c2 / scale.y, trafo.c3 / scale.z);
// and convert it into a quaternion // and convert it into a quaternion
nbone->mRotationKeys[c].mTime = time; nbone->mRotationKeys[c].mTime = time;
nbone->mRotationKeys[c].mValue = aiQuaternion( rotmat); nbone->mRotationKeys[c].mValue = aiQuaternion(rotmat);
} }
// longest lasting key sequence determines duration // longest lasting key sequence determines duration
nanim->mDuration = std::max( nanim->mDuration, bone->mTrafoKeys.back().mTime); nanim->mDuration = std::max(nanim->mDuration, bone->mTrafoKeys.back().mTime);
} else { } else {
// separate key sequences for position, rotation, scaling // separate key sequences for position, rotation, scaling
nbone->mNumPositionKeys = (unsigned int)bone->mPosKeys.size(); nbone->mNumPositionKeys = (unsigned int)bone->mPosKeys.size();
if (nbone->mNumPositionKeys != 0) { if (nbone->mNumPositionKeys != 0) {
nbone->mPositionKeys = new aiVectorKey[nbone->mNumPositionKeys]; nbone->mPositionKeys = new aiVectorKey[nbone->mNumPositionKeys];
for( unsigned int c = 0; c < nbone->mNumPositionKeys; ++c ) { for (unsigned int c = 0; c < nbone->mNumPositionKeys; ++c) {
aiVector3D pos = bone->mPosKeys[c].mValue; aiVector3D pos = bone->mPosKeys[c].mValue;
nbone->mPositionKeys[c].mTime = bone->mPosKeys[c].mTime; nbone->mPositionKeys[c].mTime = bone->mPosKeys[c].mTime;
@ -509,11 +509,11 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData
nbone->mNumRotationKeys = (unsigned int)bone->mRotKeys.size(); nbone->mNumRotationKeys = (unsigned int)bone->mRotKeys.size();
if (nbone->mNumRotationKeys != 0) { if (nbone->mNumRotationKeys != 0) {
nbone->mRotationKeys = new aiQuatKey[nbone->mNumRotationKeys]; nbone->mRotationKeys = new aiQuatKey[nbone->mNumRotationKeys];
for( unsigned int c = 0; c < nbone->mNumRotationKeys; ++c ) { for (unsigned int c = 0; c < nbone->mNumRotationKeys; ++c) {
aiMatrix3x3 rotmat = bone->mRotKeys[c].mValue.GetMatrix(); aiMatrix3x3 rotmat = bone->mRotKeys[c].mValue.GetMatrix();
nbone->mRotationKeys[c].mTime = bone->mRotKeys[c].mTime; nbone->mRotationKeys[c].mTime = bone->mRotKeys[c].mTime;
nbone->mRotationKeys[c].mValue = aiQuaternion( rotmat); nbone->mRotationKeys[c].mValue = aiQuaternion(rotmat);
nbone->mRotationKeys[c].mValue.w *= -1.0f; // needs quat inversion nbone->mRotationKeys[c].mValue.w *= -1.0f; // needs quat inversion
} }
} }
@ -522,153 +522,149 @@ void XFileImporter::CreateAnimations( aiScene* pScene, const XFile::Scene* pData
nbone->mNumScalingKeys = (unsigned int)bone->mScaleKeys.size(); nbone->mNumScalingKeys = (unsigned int)bone->mScaleKeys.size();
if (nbone->mNumScalingKeys != 0) { if (nbone->mNumScalingKeys != 0) {
nbone->mScalingKeys = new aiVectorKey[nbone->mNumScalingKeys]; nbone->mScalingKeys = new aiVectorKey[nbone->mNumScalingKeys];
for( unsigned int c = 0; c < nbone->mNumScalingKeys; c++) for (unsigned int c = 0; c < nbone->mNumScalingKeys; c++)
nbone->mScalingKeys[c] = bone->mScaleKeys[c]; nbone->mScalingKeys[c] = bone->mScaleKeys[c];
} }
// longest lasting key sequence determines duration // longest lasting key sequence determines duration
if( bone->mPosKeys.size() > 0) if (bone->mPosKeys.size() > 0)
nanim->mDuration = std::max( nanim->mDuration, bone->mPosKeys.back().mTime); nanim->mDuration = std::max(nanim->mDuration, bone->mPosKeys.back().mTime);
if( bone->mRotKeys.size() > 0) if (bone->mRotKeys.size() > 0)
nanim->mDuration = std::max( nanim->mDuration, bone->mRotKeys.back().mTime); nanim->mDuration = std::max(nanim->mDuration, bone->mRotKeys.back().mTime);
if( bone->mScaleKeys.size() > 0) if (bone->mScaleKeys.size() > 0)
nanim->mDuration = std::max( nanim->mDuration, bone->mScaleKeys.back().mTime); nanim->mDuration = std::max(nanim->mDuration, bone->mScaleKeys.back().mTime);
} }
} }
} }
// store all converted animations in the scene // store all converted animations in the scene
if( newAnims.size() > 0) if (newAnims.size() > 0) {
{
pScene->mNumAnimations = (unsigned int)newAnims.size(); pScene->mNumAnimations = (unsigned int)newAnims.size();
pScene->mAnimations = new aiAnimation* [pScene->mNumAnimations]; pScene->mAnimations = new aiAnimation *[pScene->mNumAnimations];
for( unsigned int a = 0; a < newAnims.size(); a++) for (unsigned int a = 0; a < newAnims.size(); a++)
pScene->mAnimations[a] = newAnims[a]; pScene->mAnimations[a] = newAnims[a];
} }
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Converts all materials in the given array and stores them in the scene's material list. // Converts all materials in the given array and stores them in the scene's material list.
void XFileImporter::ConvertMaterials( aiScene* pScene, std::vector<XFile::Material>& pMaterials) void XFileImporter::ConvertMaterials(aiScene *pScene, std::vector<XFile::Material> &pMaterials) {
{
// count the non-referrer materials in the array // count the non-referrer materials in the array
unsigned int numNewMaterials( 0 ); unsigned int numNewMaterials(0);
for ( unsigned int a = 0; a < pMaterials.size(); ++a ) { for (unsigned int a = 0; a < pMaterials.size(); ++a) {
if ( !pMaterials[ a ].mIsReference ) { if (!pMaterials[a].mIsReference) {
++numNewMaterials; ++numNewMaterials;
} }
} }
// resize the scene's material list to offer enough space for the new materials // resize the scene's material list to offer enough space for the new materials
if( numNewMaterials > 0 ) { if (numNewMaterials > 0) {
aiMaterial** prevMats = pScene->mMaterials; aiMaterial **prevMats = pScene->mMaterials;
pScene->mMaterials = new aiMaterial*[pScene->mNumMaterials + numNewMaterials]; pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials + numNewMaterials];
if( nullptr != prevMats) { if (nullptr != prevMats) {
::memcpy( pScene->mMaterials, prevMats, pScene->mNumMaterials * sizeof( aiMaterial*)); ::memcpy(pScene->mMaterials, prevMats, pScene->mNumMaterials * sizeof(aiMaterial *));
delete [] prevMats; delete[] prevMats;
} }
} }
// convert all the materials given in the array // convert all the materials given in the array
for( unsigned int a = 0; a < pMaterials.size(); ++a ) { for (unsigned int a = 0; a < pMaterials.size(); ++a) {
XFile::Material& oldMat = pMaterials[a]; XFile::Material &oldMat = pMaterials[a];
if( oldMat.mIsReference) { if (oldMat.mIsReference) {
// find the material it refers to by name, and store its index // find the material it refers to by name, and store its index
for( size_t b = 0; b < pScene->mNumMaterials; ++b ) { for (size_t b = 0; b < pScene->mNumMaterials; ++b) {
aiString name; aiString name;
pScene->mMaterials[b]->Get( AI_MATKEY_NAME, name); pScene->mMaterials[b]->Get(AI_MATKEY_NAME, name);
if( strcmp( name.C_Str(), oldMat.mName.data()) == 0 ) { if (strcmp(name.C_Str(), oldMat.mName.data()) == 0) {
oldMat.sceneIndex = b; oldMat.sceneIndex = b;
break; break;
} }
} }
if( oldMat.sceneIndex == SIZE_MAX ) { if (oldMat.sceneIndex == SIZE_MAX) {
ASSIMP_LOG_WARN( "Could not resolve global material reference \"", oldMat.mName, "\"" ); ASSIMP_LOG_WARN("Could not resolve global material reference \"", oldMat.mName, "\"");
oldMat.sceneIndex = 0; oldMat.sceneIndex = 0;
} }
continue; continue;
} }
aiMaterial* mat = new aiMaterial; aiMaterial *mat = new aiMaterial;
aiString name; aiString name;
name.Set( oldMat.mName); name.Set(oldMat.mName);
mat->AddProperty( &name, AI_MATKEY_NAME); mat->AddProperty(&name, AI_MATKEY_NAME);
// Shading model: hard-coded to PHONG, there is no such information in an XFile // Shading model: hard-coded to PHONG, there is no such information in an XFile
// FIX (aramis): If the specular exponent is 0, use gouraud shading. This is a bugfix // FIX (aramis): If the specular exponent is 0, use gouraud shading. This is a bugfix
// for some models in the SDK (e.g. good old tiny.x) // for some models in the SDK (e.g. good old tiny.x)
int shadeMode = (int)oldMat.mSpecularExponent == 0.0f int shadeMode = (int)oldMat.mSpecularExponent == 0.0f ? aiShadingMode_Gouraud : aiShadingMode_Phong;
? aiShadingMode_Gouraud : aiShadingMode_Phong;
mat->AddProperty<int>( &shadeMode, 1, AI_MATKEY_SHADING_MODEL); mat->AddProperty<int>(&shadeMode, 1, AI_MATKEY_SHADING_MODEL);
// material colours // material colours
// Unclear: there's no ambient colour, but emissive. What to put for ambient? // Unclear: there's no ambient colour, but emissive. What to put for ambient?
// Probably nothing at all, let the user select a suitable default. // Probably nothing at all, let the user select a suitable default.
mat->AddProperty( &oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE); mat->AddProperty(&oldMat.mEmissive, 1, AI_MATKEY_COLOR_EMISSIVE);
mat->AddProperty( &oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE); mat->AddProperty(&oldMat.mDiffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
mat->AddProperty( &oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR); mat->AddProperty(&oldMat.mSpecular, 1, AI_MATKEY_COLOR_SPECULAR);
mat->AddProperty( &oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS); mat->AddProperty(&oldMat.mSpecularExponent, 1, AI_MATKEY_SHININESS);
// texture, if there is one // texture, if there is one
if (1 == oldMat.mTextures.size() ) { if (1 == oldMat.mTextures.size()) {
const XFile::TexEntry& otex = oldMat.mTextures.back(); const XFile::TexEntry &otex = oldMat.mTextures.back();
if (otex.mName.length()) { if (otex.mName.length()) {
// if there is only one texture assume it contains the diffuse color // if there is only one texture assume it contains the diffuse color
aiString tex( otex.mName); aiString tex(otex.mName);
if ( otex.mIsNormalMap ) { if (otex.mIsNormalMap) {
mat->AddProperty( &tex, AI_MATKEY_TEXTURE_NORMALS( 0 ) ); mat->AddProperty(&tex, AI_MATKEY_TEXTURE_NORMALS(0));
} else { } else {
mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE( 0 ) ); mat->AddProperty(&tex, AI_MATKEY_TEXTURE_DIFFUSE(0));
} }
} }
} else { } else {
// Otherwise ... try to search for typical strings in the // Otherwise ... try to search for typical strings in the
// texture's file name like 'bump' or 'diffuse' // texture's file name like 'bump' or 'diffuse'
unsigned int iHM = 0,iNM = 0,iDM = 0,iSM = 0,iAM = 0,iEM = 0; unsigned int iHM = 0, iNM = 0, iDM = 0, iSM = 0, iAM = 0, iEM = 0;
for( unsigned int b = 0; b < oldMat.mTextures.size(); ++b ) { for (unsigned int b = 0; b < oldMat.mTextures.size(); ++b) {
const XFile::TexEntry& otex = oldMat.mTextures[b]; const XFile::TexEntry &otex = oldMat.mTextures[b];
std::string sz = otex.mName; std::string sz = otex.mName;
if ( !sz.length() ) { if (!sz.length()) {
continue; continue;
} }
// find the file name // find the file name
std::string::size_type s = sz.find_last_of("\\/"); std::string::size_type s = sz.find_last_of("\\/");
if ( std::string::npos == s ) { if (std::string::npos == s) {
s = 0; s = 0;
} }
// cut off the file extension // cut off the file extension
std::string::size_type sExt = sz.find_last_of('.'); std::string::size_type sExt = sz.find_last_of('.');
if (std::string::npos != sExt){ if (std::string::npos != sExt) {
sz[sExt] = '\0'; sz[sExt] = '\0';
} }
// convert to lower case for easier comparison // convert to lower case for easier comparison
for ( unsigned int c = 0; c < sz.length(); ++c ) { for (unsigned int c = 0; c < sz.length(); ++c) {
sz[ c ] = (char) tolower( (unsigned char) sz[ c ] ); sz[c] = (char)tolower((unsigned char)sz[c]);
} }
// Place texture filename property under the corresponding name // Place texture filename property under the corresponding name
aiString tex( oldMat.mTextures[b].mName); aiString tex(oldMat.mTextures[b].mName);
// bump map // bump map
if (std::string::npos != sz.find("bump", s) || std::string::npos != sz.find("height", s)) { if (std::string::npos != sz.find("bump", s) || std::string::npos != sz.find("height", s)) {
mat->AddProperty( &tex, AI_MATKEY_TEXTURE_HEIGHT(iHM++)); mat->AddProperty(&tex, AI_MATKEY_TEXTURE_HEIGHT(iHM++));
} else if (otex.mIsNormalMap || std::string::npos != sz.find( "normal", s) || std::string::npos != sz.find("nm", s)) { } else if (otex.mIsNormalMap || std::string::npos != sz.find("normal", s) || std::string::npos != sz.find("nm", s)) {
mat->AddProperty( &tex, AI_MATKEY_TEXTURE_NORMALS(iNM++)); mat->AddProperty(&tex, AI_MATKEY_TEXTURE_NORMALS(iNM++));
} else if (std::string::npos != sz.find( "spec", s) || std::string::npos != sz.find( "glanz", s)) { } else if (std::string::npos != sz.find("spec", s) || std::string::npos != sz.find("glanz", s)) {
mat->AddProperty( &tex, AI_MATKEY_TEXTURE_SPECULAR(iSM++)); mat->AddProperty(&tex, AI_MATKEY_TEXTURE_SPECULAR(iSM++));
} else if (std::string::npos != sz.find( "ambi", s) || std::string::npos != sz.find( "env", s)) { } else if (std::string::npos != sz.find("ambi", s) || std::string::npos != sz.find("env", s)) {
mat->AddProperty( &tex, AI_MATKEY_TEXTURE_AMBIENT(iAM++)); mat->AddProperty(&tex, AI_MATKEY_TEXTURE_AMBIENT(iAM++));
} else if (std::string::npos != sz.find( "emissive", s) || std::string::npos != sz.find( "self", s)) { } else if (std::string::npos != sz.find("emissive", s) || std::string::npos != sz.find("self", s)) {
mat->AddProperty( &tex, AI_MATKEY_TEXTURE_EMISSIVE(iEM++)); mat->AddProperty(&tex, AI_MATKEY_TEXTURE_EMISSIVE(iEM++));
} else { } else {
// Assume it is a diffuse texture // Assume it is a diffuse texture
mat->AddProperty( &tex, AI_MATKEY_TEXTURE_DIFFUSE(iDM++)); mat->AddProperty(&tex, AI_MATKEY_TEXTURE_DIFFUSE(iDM++));
} }
} }
} }
@ -679,4 +675,6 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, std::vector<XFile::Materi
} }
} }
} // namespace Assimp
#endif // !! ASSIMP_BUILD_NO_X_IMPORTER #endif // !! ASSIMP_BUILD_NO_X_IMPORTER

View File

@ -68,7 +68,7 @@ namespace XFile {
*/ */
class XFileImporter : public BaseImporter { class XFileImporter : public BaseImporter {
public: public:
XFileImporter(); XFileImporter() = default;
~XFileImporter() override = default; ~XFileImporter() override = default;
// ------------------------------------------------------------------- // -------------------------------------------------------------------

View File

@ -3,7 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2022, assimp team Copyright (c) 2006-2023, assimp team
All rights reserved. All rights reserved.
@ -56,64 +56,46 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory> #include <memory>
#include <utility> #include <utility>
//#include <cctype>
//#include <memory>
using namespace Assimp; namespace Assimp {
namespace Assimp { // this has to be in here because LogFunctions is in ::Assimp static constexpr uint32_t ErrorId = ~0u;
template <> template <>
const char *LogFunctions<XGLImporter>::Prefix() { const char *LogFunctions<XGLImporter>::Prefix() {
return "XGL: "; return "XGL: ";
} }
} // namespace Assimp static constexpr aiImporterDesc desc = {
"XGL Importer", "", "", "",
static const aiImporterDesc desc = { aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportCompressedFlavour,
"XGL Importer", 0, 0, 0, 0, "xgl zgl"};
"",
"",
"",
aiImporterFlags_SupportTextFlavour | aiImporterFlags_SupportCompressedFlavour,
0,
0,
0,
0,
"xgl zgl"
};
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer XGLImporter::XGLImporter() : mXmlParser(nullptr), m_scene(nullptr) {
XGLImporter::XGLImporter() :
mXmlParser(nullptr),
m_scene(nullptr) {
// empty // empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Destructor, private as well
XGLImporter::~XGLImporter() { XGLImporter::~XGLImporter() {
delete mXmlParser; clear();
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool XGLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const { bool XGLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const char *tokens[] = { "<world>", "<World>", "<WORLD>" }; static const char *tokens[] = { "<world>", "<World>", "<WORLD>" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens)); return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Get a list of all file extensions which are handled by this class
const aiImporterDesc *XGLImporter::GetInfo() const { const aiImporterDesc *XGLImporter::GetInfo() const {
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure.
void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
#ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL clear();
#ifndef ASSIMP_BUILD_NO_COMPRESSED_XGL
std::vector<char> uncompressed; std::vector<char> uncompressed;
#endif #endif
@ -159,7 +141,7 @@ void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
std::vector<aiMesh *> &meshes = scope.meshes_linear; std::vector<aiMesh *> &meshes = scope.meshes_linear;
std::vector<aiMaterial *> &materials = scope.materials_linear; std::vector<aiMaterial *> &materials = scope.materials_linear;
if (!meshes.size() || !materials.size()) { if (meshes.empty() || materials.empty()) {
ThrowException("failed to extract data from XGL file, no meshes loaded"); ThrowException("failed to extract data from XGL file, no meshes loaded");
} }
@ -184,6 +166,13 @@ void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
scope.dismiss(); scope.dismiss();
} }
// ------------------------------------------------------------------------------------------------
void XGLImporter::clear() {
delete mXmlParser;
mXmlParser = nullptr;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void XGLImporter::ReadWorld(XmlNode &node, TempScope &scope) { void XGLImporter::ReadWorld(XmlNode &node, TempScope &scope) {
for (XmlNode &currentNode : node.children()) { for (XmlNode &currentNode : node.children()) {
@ -199,9 +188,10 @@ void XGLImporter::ReadWorld(XmlNode &node, TempScope &scope) {
} }
aiNode *const nd = ReadObject(node, scope); aiNode *const nd = ReadObject(node, scope);
if (!nd) { if (nd == nullptr) {
ThrowException("failure reading <world>"); ThrowException("failure reading <world>");
} }
if (nd->mName.length == 0) { if (nd->mName.length == 0) {
nd->mName.Set("WORLD"); nd->mName.Set("WORLD");
} }
@ -254,15 +244,17 @@ aiNode *XGLImporter::ReadObject(XmlNode &node, TempScope &scope) {
const std::string &s = ai_stdStrToLower(child.name()); const std::string &s = ai_stdStrToLower(child.name());
if (s == "mesh") { if (s == "mesh") {
const size_t prev = scope.meshes_linear.size(); const size_t prev = scope.meshes_linear.size();
bool empty; if (ReadMesh(child, scope)) {
if (ReadMesh(child, scope, empty)) {
const size_t newc = scope.meshes_linear.size(); const size_t newc = scope.meshes_linear.size();
for (size_t i = 0; i < newc - prev; ++i) { for (size_t i = 0; i < newc - prev; ++i) {
meshes.push_back(static_cast<unsigned int>(i + prev)); meshes.push_back(static_cast<unsigned int>(i + prev));
} }
} }
} else if (s == "mat") { } else if (s == "mat") {
ReadMaterial(child, scope); const uint32_t matId = ReadMaterial(child, scope);
if (matId == ErrorId) {
ThrowException("Invalid material id detected.");
}
} else if (s == "object") { } else if (s == "object") {
children.push_back(ReadObject(child, scope)); children.push_back(ReadObject(child, scope));
} else if (s == "objectref") { } else if (s == "objectref") {
@ -438,18 +430,25 @@ aiMesh *XGLImporter::ToOutputMesh(const TempMaterialMesh &m) {
return mesh.release(); return mesh.release();
} }
// ------------------------------------------------------------------------------------------------
bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope, bool &empty) {
TempMesh t;
// ------------------------------------------------------------------------------------------------
inline static unsigned int generateMeshId(unsigned int meshId, bool nor, bool uv) {
unsigned int currentMeshId = meshId | ((nor ? 1 : 0) << 31) | ((uv ? 1 : 0) << 30);
return currentMeshId;
}
// ------------------------------------------------------------------------------------------------
bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope) {
TempMesh t;
uint32_t matId = 99999;
bool mesh_created = false;
std::map<unsigned int, TempMaterialMesh> bymat; std::map<unsigned int, TempMaterialMesh> bymat;
const unsigned int mesh_id = ReadIDAttr(node); const unsigned int mesh_id = ReadIDAttr(node);
bool empty_mesh = true;
for (XmlNode &child : node.children()) { for (XmlNode &child : node.children()) {
const std::string &s = ai_stdStrToLower(child.name()); const std::string &s = ai_stdStrToLower(child.name());
if (s == "mat") { if (s == "mat") {
ReadMaterial(child, scope); matId = ReadMaterial(child, scope);
} else if (s == "p") { } else if (s == "p") {
pugi::xml_attribute attr = child.attribute("ID"); pugi::xml_attribute attr = child.attribute("ID");
if (attr.empty()) { if (attr.empty()) {
@ -477,66 +476,41 @@ bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope, bool &empty) {
} else if (s == "f" || s == "l" || s == "p") { } else if (s == "f" || s == "l" || s == "p") {
const unsigned int vcount = s == "f" ? 3 : (s == "l" ? 2 : 1); const unsigned int vcount = s == "f" ? 3 : (s == "l" ? 2 : 1);
unsigned int mid = ~0u; unsigned int meshId = ErrorId;
TempFace tf[3]; TempFace tempFace[3] = {};
bool has[3] = { false }; bool has[3] = { false };
for (XmlNode &sub_child : child.children()) { meshId = ReadVertices(child, t, tempFace, has, meshId, scope);
const std::string &scn = ai_stdStrToLower(sub_child.name()); if (meshId == ErrorId) {
if (scn == "fv1" || scn == "lv1" || scn == "pv1") {
ReadFaceVertex(sub_child, t, tf[0]);
has[0] = true;
} else if (scn == "fv2" || scn == "lv2") {
ReadFaceVertex(sub_child, t, tf[1]);
has[1] = true;
} else if (scn == "fv3") {
ReadFaceVertex(sub_child, t, tf[2]);
has[2] = true;
} else if (scn == "mat") {
if (mid != ~0u) {
LogWarn("only one material tag allowed per <f>");
}
mid = ResolveMaterialRef(sub_child, scope);
} else if (scn == "matref") {
if (mid != ~0u) {
LogWarn("only one material tag allowed per <f>");
}
mid = ResolveMaterialRef(sub_child, scope);
}
}
if (has[0] || has[1] || has[2]) {
empty_mesh = false;
}
if (mid == ~0u) {
ThrowException("missing material index"); ThrowException("missing material index");
} }
bool nor = false; bool nor = false, uv = false;
bool uv = false;
for (unsigned int i = 0; i < vcount; ++i) { for (unsigned int i = 0; i < vcount; ++i) {
if (!has[i]) { if (!has[i]) {
ThrowException("missing face vertex data"); ThrowException("missing face vertex data");
} }
nor = nor || tf[i].has_normal; nor = nor || tempFace[i].has_normal;
uv = uv || tf[i].has_uv; uv = uv || tempFace[i].has_uv;
} }
if (mid >= (1 << 30)) { if (meshId >= (1 << 30)) {
LogWarn("material indices exhausted, this may cause errors in the output"); LogWarn("material indices exhausted, this may cause errors in the output");
} }
unsigned int meshId = mid | ((nor ? 1 : 0) << 31) | ((uv ? 1 : 0) << 30); const unsigned int currentMeshId = generateMeshId(meshId, nor, uv);
TempMaterialMesh &mesh = bymat[meshId]; // Generate the temp mesh
mesh.matid = mid; TempMaterialMesh &mesh = bymat[currentMeshId];
mesh.matid = meshId;
mesh_created = true;
for (unsigned int i = 0; i < vcount; ++i) { for (unsigned int i = 0; i < vcount; ++i) {
mesh.positions.push_back(tf[i].pos); mesh.positions.push_back(tempFace[i].pos);
if (nor) { if (nor) {
mesh.normals.push_back(tf[i].normal); mesh.normals.push_back(tempFace[i].normal);
} }
if (uv) { if (uv) {
mesh.uvs.push_back(tf[i].uv); mesh.uvs.push_back(tempFace[i].uv);
} }
mesh.pflags |= 1 << (vcount - 1); mesh.pflags |= 1 << (vcount - 1);
@ -546,25 +520,59 @@ bool XGLImporter::ReadMesh(XmlNode &node, TempScope &scope, bool &empty) {
} }
} }
// finally extract output meshes and add them to the scope if (!mesh_created) {
using pairt = std::pair<const unsigned int, TempMaterialMesh>; TempMaterialMesh &mesh = bymat[mesh_id];
for (const pairt &p : bymat) { mesh.matid = matId;
aiMesh *const m = ToOutputMesh(p.second);
scope.meshes_linear.push_back(m);
// if this is a definition, keep it on the stack
if (mesh_id != ~0u) {
scope.meshes.insert(std::pair<unsigned int, aiMesh *>(mesh_id, m));
}
}
if (empty_mesh) {
LogWarn("Mesh is empty, skipping.");
empty = empty_mesh;
return false;
} }
// finally extract output meshes and add them to the scope
AppendOutputMeshes(bymat, scope, mesh_id);
// no id == not a reference, insert this mesh right *here* // no id == not a reference, insert this mesh right *here*
return mesh_id == ~0u; return mesh_id == ErrorId;
}
// ----------------------------------------------------------------------------------------------
void XGLImporter::AppendOutputMeshes(std::map<unsigned int, TempMaterialMesh> bymat, TempScope &scope,
const unsigned int mesh_id) {
using pairt = std::pair<const unsigned int, TempMaterialMesh>;
for (const pairt &p : bymat) {
aiMesh *const m = ToOutputMesh(p.second);
scope.meshes_linear.push_back(m);
// if this is a definition, keep it on the stack
if (mesh_id != ErrorId) {
scope.meshes.insert(std::pair<unsigned int, aiMesh *>(mesh_id, m));
}
}
}
// ----------------------------------------------------------------------------------------------
unsigned int XGLImporter::ReadVertices(XmlNode &child, TempMesh t, TempFace *tf, bool *has, unsigned int mid, TempScope &scope) {
for (XmlNode &sub_child : child.children()) {
const std::string &scn = ai_stdStrToLower(sub_child.name());
if (scn == "fv1" || scn == "lv1" || scn == "pv1") {
ReadFaceVertex(sub_child, t, tf[0]);
has[0] = true;
} else if (scn == "fv2" || scn == "lv2") {
ReadFaceVertex(sub_child, t, tf[1]);
has[1] = true;
} else if (scn == "fv3") {
ReadFaceVertex(sub_child, t, tf[2]);
has[2] = true;
} else if (scn == "mat") {
if (mid != ErrorId) {
LogWarn("only one material tag allowed per <f>");
}
mid = ResolveMaterialRef(sub_child, scope);
} else if (scn == "matref") {
if (mid != ErrorId) {
LogWarn("only one material tag allowed per <f>");
}
mid = ResolveMaterialRef(sub_child, scope);
}
}
return mid;
} }
// ---------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------
@ -598,10 +606,10 @@ unsigned int XGLImporter::ResolveMaterialRef(XmlNode &node, TempScope &scope) {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void XGLImporter::ReadMaterial(XmlNode &node, TempScope &scope) { unsigned int XGLImporter::ReadMaterial(XmlNode &node, TempScope &scope) {
const unsigned int mat_id = ReadIDAttr(node); const unsigned int mat_id = ReadIDAttr(node);
auto *mat(new aiMaterial); auto *mat = new aiMaterial;
for (XmlNode &child : node.children()) { for (XmlNode &child : node.children()) {
const std::string &s = ai_stdStrToLower(child.name()); const std::string &s = ai_stdStrToLower(child.name());
if (s == "amb") { if (s == "amb") {
@ -627,6 +635,8 @@ void XGLImporter::ReadMaterial(XmlNode &node, TempScope &scope) {
scope.materials[mat_id] = mat; scope.materials[mat_id] = mat;
scope.materials_linear.push_back(mat); scope.materials_linear.push_back(mat);
return mat_id;
} }
// ---------------------------------------------------------------------------------------------- // ----------------------------------------------------------------------------------------------
@ -683,7 +693,7 @@ unsigned int XGLImporter::ReadIDAttr(XmlNode &node) {
} }
} }
return ~0u; return ErrorId;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -712,14 +722,14 @@ unsigned int XGLImporter::ReadIndexFromText(XmlNode &node) {
const char *s = v.c_str(); const char *s = v.c_str();
if (!SkipSpaces(&s)) { if (!SkipSpaces(&s)) {
LogError("unexpected EOL, failed to parse index element"); LogError("unexpected EOL, failed to parse index element");
return ~0u; return ErrorId;
} }
const char *se; const char *se = nullptr;
const unsigned int t = strtoul10(s, &se); const unsigned int t = strtoul10(s, &se);
if (se == s) { if (se == s) {
LogError("failed to read index"); LogError("failed to read index");
return ~0u; return ErrorId;
} }
return t; return t;
@ -786,4 +796,6 @@ aiColor3D XGLImporter::ReadCol3(XmlNode &node) {
return aiColor3D(v.x, v.y, v.z); return aiColor3D(v.x, v.y, v.z);
} }
} // namespace Assimp
#endif // ASSIMP_BUILD_NO_XGL_IMPORTER #endif // ASSIMP_BUILD_NO_XGL_IMPORTER

View File

@ -69,16 +69,20 @@ namespace Assimp {
*/ */
class XGLImporter : public BaseImporter, public LogFunctions<XGLImporter> { class XGLImporter : public BaseImporter, public LogFunctions<XGLImporter> {
public: public:
/// @brief The class constructor.
XGLImporter(); XGLImporter();
/// @brief The class destructor.
~XGLImporter() override; ~XGLImporter() override;
// ------------------------------------------------------------------- /// @brief Returns whether the class can handle the format of the given file.
/** Returns whether the class can handle the format of the given file. /// @see BaseImporter::CanRead() for details. */
* See BaseImporter::CanRead() for details. */
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool CanRead(const std::string &pFile, IOSystem *pIOHandler,
bool checkSig) const override; bool checkSig) const override;
protected: protected:
void clear();
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Return importer meta information. /** Return importer meta information.
* See #BaseImporter::GetInfo for the details */ * See #BaseImporter::GetInfo for the details */
@ -92,10 +96,7 @@ protected:
private: private:
struct TempScope { struct TempScope {
TempScope() : TempScope() : light() {}
light() {
// empty
}
~TempScope() { ~TempScope() {
for (aiMesh *m : meshes_linear) { for (aiMesh *m : meshes_linear) {
@ -145,9 +146,7 @@ private:
}; };
struct TempMaterialMesh { struct TempMaterialMesh {
TempMaterialMesh() : TempMaterialMesh() : pflags(), matid() {
pflags(),
matid() {
// empty // empty
} }
@ -160,9 +159,7 @@ private:
}; };
struct TempFace { struct TempFace {
TempFace() : TempFace() : has_uv(), has_normal() {
has_uv(),
has_normal() {
// empty // empty
} }
@ -175,26 +172,25 @@ private:
private: private:
void Cleanup(); void Cleanup();
std::string GetElementName(); std::string GetElementName();
bool ReadElement(); bool ReadElement();
bool ReadElementUpToClosing(const char *closetag); bool ReadElementUpToClosing(const char *closetag);
bool SkipToText(); bool SkipToText();
unsigned int ReadIDAttr(XmlNode &node); unsigned int ReadIDAttr(XmlNode &node);
void ReadWorld(XmlNode &node, TempScope &scope); void ReadWorld(XmlNode &node, TempScope &scope);
void ReadLighting(XmlNode &node, TempScope &scope); void ReadLighting(XmlNode &node, TempScope &scope);
aiLight *ReadDirectionalLight(XmlNode &node); aiLight *ReadDirectionalLight(XmlNode &node);
aiNode *ReadObject(XmlNode &node, TempScope &scope); aiNode *ReadObject(XmlNode &node, TempScope &scope);
bool ReadMesh(XmlNode &node, TempScope &scope, bool &empty); bool ReadMesh(XmlNode &node, TempScope &scope);
void ReadMaterial(XmlNode &node, TempScope &scope); void AppendOutputMeshes(std::map<unsigned int, TempMaterialMesh> bymat, TempScope &scope, const unsigned int mesh_id);
unsigned int ReadVertices(XmlNode &child, TempMesh t, TempFace *tf, bool *has, unsigned int mid, TempScope &scope);
unsigned int ReadMaterial(XmlNode &node, TempScope &scope);
aiVector2D ReadVec2(XmlNode &node); aiVector2D ReadVec2(XmlNode &node);
aiVector3D ReadVec3(XmlNode &node); aiVector3D ReadVec3(XmlNode &node);
aiColor3D ReadCol3(XmlNode &node); aiColor3D ReadCol3(XmlNode &node);
aiMatrix4x4 ReadTrafo(XmlNode &node); aiMatrix4x4 ReadTrafo(XmlNode &node);
unsigned int ReadIndexFromText(XmlNode &node); unsigned int ReadIndexFromText(XmlNode &node);
float ReadFloat(XmlNode &node); float ReadFloat(XmlNode &node);
aiMesh *ToOutputMesh(const TempMaterialMesh &m); aiMesh *ToOutputMesh(const TempMaterialMesh &m);
void ReadFaceVertex(XmlNode &node, const TempMesh &t, TempFace &out); void ReadFaceVertex(XmlNode &node, const TempMesh &t, TempFace &out);
unsigned int ResolveMaterialRef(XmlNode &node, TempScope &scope); unsigned int ResolveMaterialRef(XmlNode &node, TempScope &scope);

View File

@ -62,11 +62,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp; using namespace Assimp;
using namespace glTF; using namespace glTF;
// static constexpr aiImporterDesc desc = {
// glTFImporter
//
static const aiImporterDesc desc = {
"glTF Importer", "glTF Importer",
"", "",
"", "",

View File

@ -172,22 +172,6 @@ static void IdentityMatrix4(mat4 &o) {
o[15] = 1; o[15] = 1;
} }
static bool IsBoneWeightFitted(vec4 &weight) {
return weight[0] + weight[1] + weight[2] + weight[3] >= 1.f;
}
static int FitBoneWeight(vec4 &weight, float value) {
int i = 0;
for (; i < 4; ++i) {
if (weight[i] < value) {
weight[i] = value;
return i;
}
}
return -1;
}
template <typename T> template <typename T>
void SetAccessorRange(Ref<Accessor> acc, void *data, size_t count, void SetAccessorRange(Ref<Accessor> acc, void *data, size_t count,
unsigned int numCompsIn, unsigned int numCompsOut) { unsigned int numCompsIn, unsigned int numCompsOut) {
@ -575,7 +559,11 @@ void glTF2Exporter::GetMatTex(const aiMaterial &mat, Ref<Texture> &texture, unsi
aiString tex; aiString tex;
// Read texcoord (UV map index) // Read texcoord (UV map index)
mat.Get(AI_MATKEY_UVWSRC(tt, slot), texCoord); // Note: must be an int to be successful.
int tmp = 0;
const auto ok = mat.Get(AI_MATKEY_UVWSRC(tt, slot), tmp);
if (ok == aiReturn_SUCCESS) texCoord = tmp;
if (mat.Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) { if (mat.Get(AI_MATKEY_TEXTURE(tt, slot), tex) == AI_SUCCESS) {
std::string path = tex.C_Str(); std::string path = tex.C_Str();
@ -1009,23 +997,29 @@ Ref<Node> FindSkeletonRootJoint(Ref<Skin> &skinRef) {
return parentNodeRef; return parentNodeRef;
} }
struct boneIndexWeightPair {
unsigned int indexJoint;
float weight;
bool operator()(boneIndexWeightPair &a, boneIndexWeightPair &b) {
return a.weight > b.weight;
}
};
void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref<Mesh> &meshRef, Ref<Buffer> &bufferRef, Ref<Skin> &skinRef, void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref<Mesh> &meshRef, Ref<Buffer> &bufferRef, Ref<Skin> &skinRef,
std::vector<aiMatrix4x4> &inverseBindMatricesData) { std::vector<aiMatrix4x4> &inverseBindMatricesData, bool unlimitedBonesPerVertex) {
if (aimesh->mNumBones < 1) { if (aimesh->mNumBones < 1) {
return; return;
} }
// Store the vertex joint and weight data. // Store the vertex joint and weight data.
const size_t NumVerts(aimesh->mNumVertices); const size_t NumVerts(aimesh->mNumVertices);
vec4 *vertexJointData = new vec4[NumVerts];
vec4 *vertexWeightData = new vec4[NumVerts];
int *jointsPerVertex = new int[NumVerts]; int *jointsPerVertex = new int[NumVerts];
std::vector<std::vector<boneIndexWeightPair>> allVerticesPairs;
int maxJointsPerVertex = 0;
for (size_t i = 0; i < NumVerts; ++i) { for (size_t i = 0; i < NumVerts; ++i) {
jointsPerVertex[i] = 0; jointsPerVertex[i] = 0;
for (size_t j = 0; j < 4; ++j) { std::vector<boneIndexWeightPair> vertexPair;
vertexJointData[i][j] = 0; allVerticesPairs.push_back(vertexPair);
vertexWeightData[i][j] = 0;
}
} }
for (unsigned int idx_bone = 0; idx_bone < aimesh->mNumBones; ++idx_bone) { for (unsigned int idx_bone = 0; idx_bone < aimesh->mNumBones; ++idx_bone) {
@ -1055,61 +1049,88 @@ void ExportSkin(Asset &mAsset, const aiMesh *aimesh, Ref<Mesh> &meshRef, Ref<Buf
jointNamesIndex = static_cast<unsigned int>(inverseBindMatricesData.size() - 1); jointNamesIndex = static_cast<unsigned int>(inverseBindMatricesData.size() - 1);
} }
// aib->mWeights =====> vertexWeightData // aib->mWeights =====> temp pairs data
for (unsigned int idx_weights = 0; idx_weights < aib->mNumWeights; ++idx_weights) { for (unsigned int idx_weights = 0; idx_weights < aib->mNumWeights;
++idx_weights) {
unsigned int vertexId = aib->mWeights[idx_weights].mVertexId; unsigned int vertexId = aib->mWeights[idx_weights].mVertexId;
float vertWeight = aib->mWeights[idx_weights].mWeight; float vertWeight = aib->mWeights[idx_weights].mWeight;
allVerticesPairs[vertexId].push_back({jointNamesIndex, vertWeight});
// A vertex can only have at most four joint weights, which ideally sum up to 1 jointsPerVertex[vertexId] += 1;
if (IsBoneWeightFitted(vertexWeightData[vertexId])) { maxJointsPerVertex =
continue; std::max(maxJointsPerVertex, jointsPerVertex[vertexId]);
}
if (jointsPerVertex[vertexId] > 3) {
int boneIndexFitted = FitBoneWeight(vertexWeightData[vertexId], vertWeight);
if (boneIndexFitted != -1) {
vertexJointData[vertexId][boneIndexFitted] = static_cast<float>(jointNamesIndex);
}
} else {
vertexJointData[vertexId][jointsPerVertex[vertexId]] = static_cast<float>(jointNamesIndex);
vertexWeightData[vertexId][jointsPerVertex[vertexId]] = vertWeight;
jointsPerVertex[vertexId] += 1;
}
} }
} // End: for-loop mNumMeshes } // End: for-loop mNumMeshes
Mesh::Primitive &p = meshRef->primitives.back(); if (!unlimitedBonesPerVertex){
Ref<Accessor> vertexJointAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, // skinning limited only for 4 bones per vertex, default
vertexJointData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); maxJointsPerVertex = 4;
if (vertexJointAccessor) {
size_t offset = vertexJointAccessor->bufferView->byteOffset;
size_t bytesLen = vertexJointAccessor->bufferView->byteLength;
unsigned int s_bytesPerComp = ComponentTypeSize(ComponentType_UNSIGNED_SHORT);
unsigned int bytesPerComp = ComponentTypeSize(vertexJointAccessor->componentType);
size_t s_bytesLen = bytesLen * s_bytesPerComp / bytesPerComp;
Ref<Buffer> buf = vertexJointAccessor->bufferView->buffer;
uint8_t *arrys = new uint8_t[bytesLen];
unsigned int i = 0;
for (unsigned int j = 0; j < bytesLen; j += bytesPerComp) {
size_t len_p = offset + j;
float f_value = *(float *)&buf->GetPointer()[len_p];
unsigned short c = static_cast<unsigned short>(f_value);
memcpy(&arrys[i * s_bytesPerComp], &c, s_bytesPerComp);
++i;
}
buf->ReplaceData_joint(offset, bytesLen, arrys, bytesLen);
vertexJointAccessor->componentType = ComponentType_UNSIGNED_SHORT;
vertexJointAccessor->bufferView->byteLength = s_bytesLen;
p.attributes.joint.push_back(vertexJointAccessor);
delete[] arrys;
} }
Ref<Accessor> vertexWeightAccessor = ExportData(mAsset, skinRef->id, bufferRef, aimesh->mNumVertices, // temp pairs data =====> vertexWeightData
vertexWeightData, AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT); size_t numGroups = (maxJointsPerVertex - 1) / 4 + 1;
if (vertexWeightAccessor) { vec4 *vertexJointData = new vec4[NumVerts * numGroups];
p.attributes.weight.push_back(vertexWeightAccessor); vec4 *vertexWeightData = new vec4[NumVerts * numGroups];
for (size_t indexVertex = 0; indexVertex < NumVerts; ++indexVertex) {
// order pairs by weight for each vertex
std::sort(allVerticesPairs[indexVertex].begin(),
allVerticesPairs[indexVertex].end(),
boneIndexWeightPair());
for (size_t indexGroup = 0; indexGroup < numGroups; ++indexGroup) {
for (size_t indexJoint = 0; indexJoint < 4; ++indexJoint) {
size_t indexBone = indexGroup * 4 + indexJoint;
size_t indexData = indexVertex + NumVerts * indexGroup;
if (indexBone >= allVerticesPairs[indexVertex].size()) {
vertexJointData[indexData][indexJoint] = 0.f;
vertexWeightData[indexData][indexJoint] = 0.f;
} else {
vertexJointData[indexData][indexJoint] =
static_cast<float>(
allVerticesPairs[indexVertex][indexBone].indexJoint);
vertexWeightData[indexData][indexJoint] =
allVerticesPairs[indexVertex][indexBone].weight;
}
}
}
}
for (size_t idx_group = 0; idx_group < numGroups; ++idx_group) {
Mesh::Primitive &p = meshRef->primitives.back();
Ref<Accessor> vertexJointAccessor = ExportData(
mAsset, skinRef->id, bufferRef, aimesh->mNumVertices,
vertexJointData + idx_group * NumVerts,
AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
if (vertexJointAccessor) {
size_t offset = vertexJointAccessor->bufferView->byteOffset;
size_t bytesLen = vertexJointAccessor->bufferView->byteLength;
unsigned int s_bytesPerComp =
ComponentTypeSize(ComponentType_UNSIGNED_SHORT);
unsigned int bytesPerComp =
ComponentTypeSize(vertexJointAccessor->componentType);
size_t s_bytesLen = bytesLen * s_bytesPerComp / bytesPerComp;
Ref<Buffer> buf = vertexJointAccessor->bufferView->buffer;
uint8_t *arrys = new uint8_t[bytesLen];
unsigned int i = 0;
for (unsigned int j = 0; j < bytesLen; j += bytesPerComp) {
size_t len_p = offset + j;
float f_value = *(float *)&buf->GetPointer()[len_p];
unsigned short c = static_cast<unsigned short>(f_value);
memcpy(&arrys[i * s_bytesPerComp], &c, s_bytesPerComp);
++i;
}
buf->ReplaceData_joint(offset, bytesLen, arrys, bytesLen);
vertexJointAccessor->componentType = ComponentType_UNSIGNED_SHORT;
vertexJointAccessor->bufferView->byteLength = s_bytesLen;
p.attributes.joint.push_back(vertexJointAccessor);
delete[] arrys;
}
Ref<Accessor> vertexWeightAccessor = ExportData(
mAsset, skinRef->id, bufferRef, aimesh->mNumVertices,
vertexWeightData + idx_group * NumVerts,
AttribType::VEC4, AttribType::VEC4, ComponentType_FLOAT);
if (vertexWeightAccessor) {
p.attributes.weight.push_back(vertexWeightAccessor);
}
} }
delete[] jointsPerVertex; delete[] jointsPerVertex;
delete[] vertexWeightData; delete[] vertexWeightData;
@ -1247,9 +1268,19 @@ void glTF2Exporter::ExportMeshes() {
break; break;
} }
// /*************** Skins ****************/
// if (aim->HasBones()) {
// ExportSkin(*mAsset, aim, m, b, skinRef, inverseBindMatricesData);
// }
/*************** Skins ****************/ /*************** Skins ****************/
if (aim->HasBones()) { if (aim->HasBones()) {
ExportSkin(*mAsset, aim, m, b, skinRef, inverseBindMatricesData); bool unlimitedBonesPerVertex =
this->mProperties->HasPropertyBool(
AI_CONFIG_EXPORT_GLTF_UNLIMITED_SKINNING_BONES_PER_VERTEX) &&
this->mProperties->GetPropertyBool(
AI_CONFIG_EXPORT_GLTF_UNLIMITED_SKINNING_BONES_PER_VERTEX);
ExportSkin(*mAsset, aim, m, b, skinRef, inverseBindMatricesData,
unlimitedBonesPerVertex);
} }
/*************** Targets for blendshapes ****************/ /*************** Targets for blendshapes ****************/

View File

@ -82,7 +82,7 @@ struct Tangent {
// glTF2Importer // glTF2Importer
// //
static const aiImporterDesc desc = { static constexpr aiImporterDesc desc = {
"glTF2 Importer", "glTF2 Importer",
"", "",
"", "",

View File

@ -923,7 +923,7 @@ IF(ASSIMP_HUNTER_ENABLED)
hunter_add_package(utf8) hunter_add_package(utf8)
find_package(utf8cpp CONFIG REQUIRED) find_package(utf8cpp CONFIG REQUIRED)
ELSE() ELSE()
# utf8 is header-only, so Assimp doesn't need to do anything. INCLUDE_DIRECTORIES("../contrib/utf8cpp/source")
ENDIF() ENDIF()
# polyclipping # polyclipping
@ -1380,7 +1380,12 @@ ENDIF()
IF(NOT ASSIMP_HUNTER_ENABLED) IF(NOT ASSIMP_HUNTER_ENABLED)
if (UNZIP_FOUND) if (UNZIP_FOUND)
INCLUDE_DIRECTORIES(${UNZIP_INCLUDE_DIRS}) INCLUDE_DIRECTORIES(${UNZIP_INCLUDE_DIRS})
TARGET_LINK_LIBRARIES(assimp ${UNZIP_LIBRARIES}) # TODO if cmake required version has been updated to >3.12.0, collapse this to the second case only
if(${CMAKE_VERSION} VERSION_LESS "3.12.0")
TARGET_LINK_LIBRARIES(assimp ${UNZIP_LIBRARIES})
else()
TARGET_LINK_LIBRARIES(assimp ${UNZIP_LINK_LIBRARIES})
endif()
else () else ()
INCLUDE_DIRECTORIES("../") INCLUDE_DIRECTORIES("../")
endif () endif ()

View File

@ -66,6 +66,10 @@ Compression::Compression() :
Compression::~Compression() { Compression::~Compression() {
ai_assert(mImpl != nullptr); ai_assert(mImpl != nullptr);
if (mImpl->mOpen) {
close();
}
delete mImpl; delete mImpl;
} }
@ -124,7 +128,7 @@ static int getFlushMode(Compression::FlushMode flush) {
return z_flush; return z_flush;
} }
constexpr size_t MYBLOCK = 32786; static constexpr size_t MYBLOCK = 32786;
size_t Compression::decompress(const void *data, size_t in, std::vector<char> &uncompressed) { size_t Compression::decompress(const void *data, size_t in, std::vector<char> &uncompressed) {
ai_assert(mImpl != nullptr); ai_assert(mImpl != nullptr);

View File

@ -3,9 +3,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Copyright (c) 2006-2022, assimp team Copyright (c) 2006-2023, assimp team
All rights reserved. All rights reserved.
@ -59,31 +57,31 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <stdio.h> #include <stdio.h>
#include <stack> #include <stack>
using namespace Assimp; namespace Assimp {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
ImproveCacheLocalityProcess::ImproveCacheLocalityProcess() ImproveCacheLocalityProcess::ImproveCacheLocalityProcess() :
: mConfigCacheDepth(PP_ICL_PTCACHE_SIZE) { mConfigCacheDepth(PP_ICL_PTCACHE_SIZE) {
// empty // empty
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Returns whether the processing step is present in the given flag field. // Returns whether the processing step is present in the given flag field.
bool ImproveCacheLocalityProcess::IsActive( unsigned int pFlags) const { bool ImproveCacheLocalityProcess::IsActive(unsigned int pFlags) const {
return (pFlags & aiProcess_ImproveCacheLocality) != 0; return (pFlags & aiProcess_ImproveCacheLocality) != 0;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Setup configuration // Setup configuration
void ImproveCacheLocalityProcess::SetupProperties(const Importer* pImp) { void ImproveCacheLocalityProcess::SetupProperties(const Importer *pImp) {
// AI_CONFIG_PP_ICL_PTCACHE_SIZE controls the target cache size for the optimizer // AI_CONFIG_PP_ICL_PTCACHE_SIZE controls the target cache size for the optimizer
mConfigCacheDepth = pImp->GetPropertyInteger(AI_CONFIG_PP_ICL_PTCACHE_SIZE,PP_ICL_PTCACHE_SIZE); mConfigCacheDepth = pImp->GetPropertyInteger(AI_CONFIG_PP_ICL_PTCACHE_SIZE, PP_ICL_PTCACHE_SIZE);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Executes the post processing step on the given imported data. // Executes the post processing step on the given imported data.
void ImproveCacheLocalityProcess::Execute( aiScene* pScene) { void ImproveCacheLocalityProcess::Execute(aiScene *pScene) {
if (!pScene->mNumMeshes) { if (!pScene->mNumMeshes) {
ASSIMP_LOG_DEBUG("ImproveCacheLocalityProcess skipped; there are no meshes"); ASSIMP_LOG_DEBUG("ImproveCacheLocalityProcess skipped; there are no meshes");
return; return;
@ -93,11 +91,11 @@ void ImproveCacheLocalityProcess::Execute( aiScene* pScene) {
float out = 0.f; float out = 0.f;
unsigned int numf = 0, numm = 0; unsigned int numf = 0, numm = 0;
for( unsigned int a = 0; a < pScene->mNumMeshes; ++a ){ for (unsigned int a = 0; a < pScene->mNumMeshes; ++a) {
const float res = ProcessMesh( pScene->mMeshes[a],a); const float res = ProcessMesh(pScene->mMeshes[a], a);
if (res) { if (res) {
numf += pScene->mMeshes[a]->mNumFaces; numf += pScene->mMeshes[a]->mNumFaces;
out += res; out += res;
++numm; ++numm;
} }
} }
@ -109,9 +107,54 @@ void ImproveCacheLocalityProcess::Execute( aiScene* pScene) {
} }
} }
// ------------------------------------------------------------------------------------------------
static ai_real calculateInputACMR(aiMesh *pMesh, const aiFace *const pcEnd,
unsigned int configCacheDepth, unsigned int meshNum) {
ai_real fACMR = 0.0f;
unsigned int *piFIFOStack = new unsigned int[configCacheDepth];
memset(piFIFOStack, 0xff, configCacheDepth * sizeof(unsigned int));
unsigned int *piCur = piFIFOStack;
const unsigned int *const piCurEnd = piFIFOStack + configCacheDepth;
// count the number of cache misses
unsigned int iCacheMisses = 0;
for (const aiFace *pcFace = pMesh->mFaces; pcFace != pcEnd; ++pcFace) {
for (unsigned int qq = 0; qq < 3; ++qq) {
bool bInCache = false;
for (unsigned int *pp = piFIFOStack; pp < piCurEnd; ++pp) {
if (*pp == pcFace->mIndices[qq]) {
// the vertex is in cache
bInCache = true;
break;
}
}
if (!bInCache) {
++iCacheMisses;
if (piCurEnd == piCur) {
piCur = piFIFOStack;
}
*piCur++ = pcFace->mIndices[qq];
}
}
}
delete[] piFIFOStack;
fACMR = (ai_real)iCacheMisses / pMesh->mNumFaces;
if (3.0 == fACMR) {
char szBuff[128]; // should be sufficiently large in every case
// the JoinIdenticalVertices process has not been executed on this
// mesh, otherwise this value would normally be at least minimally
// smaller than 3.0 ...
ai_snprintf(szBuff, 128, "Mesh %u: Not suitable for vcache optimization", meshNum);
ASSIMP_LOG_WARN(szBuff);
return static_cast<ai_real>(0.f);
}
return fACMR;
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Improves the cache coherency of a specific mesh // Improves the cache coherency of a specific mesh
ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int meshNum) { ai_real ImproveCacheLocalityProcess::ProcessMesh(aiMesh *pMesh, unsigned int meshNum) {
// TODO: rewrite this to use std::vector or boost::shared_array // TODO: rewrite this to use std::vector or boost::shared_array
ai_assert(nullptr != pMesh); ai_assert(nullptr != pMesh);
@ -126,91 +169,57 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me
return static_cast<ai_real>(0.f); return static_cast<ai_real>(0.f);
} }
if(pMesh->mNumVertices <= mConfigCacheDepth) { if (pMesh->mNumVertices <= mConfigCacheDepth) {
return static_cast<ai_real>(0.f); return static_cast<ai_real>(0.f);
} }
ai_real fACMR = 3.f; ai_real fACMR = 3.f;
const aiFace* const pcEnd = pMesh->mFaces+pMesh->mNumFaces; const aiFace *const pcEnd = pMesh->mFaces + pMesh->mNumFaces;
// Input ACMR is for logging purposes only // Input ACMR is for logging purposes only
if (!DefaultLogger::isNullLogger()) { if (!DefaultLogger::isNullLogger()) {
fACMR = calculateInputACMR(pMesh, pcEnd, mConfigCacheDepth, meshNum);
unsigned int* piFIFOStack = new unsigned int[mConfigCacheDepth];
memset(piFIFOStack,0xff,mConfigCacheDepth*sizeof(unsigned int));
unsigned int* piCur = piFIFOStack;
const unsigned int* const piCurEnd = piFIFOStack + mConfigCacheDepth;
// count the number of cache misses
unsigned int iCacheMisses = 0;
for (const aiFace* pcFace = pMesh->mFaces;pcFace != pcEnd;++pcFace) {
for (unsigned int qq = 0; qq < 3;++qq) {
bool bInCache = false;
for (unsigned int* pp = piFIFOStack;pp < piCurEnd;++pp) {
if (*pp == pcFace->mIndices[qq]) {
// the vertex is in cache
bInCache = true;
break;
}
}
if (!bInCache) {
++iCacheMisses;
if (piCurEnd == piCur) {
piCur = piFIFOStack;
}
*piCur++ = pcFace->mIndices[qq];
}
}
}
delete[] piFIFOStack;
fACMR = (ai_real) iCacheMisses / pMesh->mNumFaces;
if (3.0 == fACMR) {
char szBuff[128]; // should be sufficiently large in every case
// the JoinIdenticalVertices process has not been executed on this
// mesh, otherwise this value would normally be at least minimally
// smaller than 3.0 ...
ai_snprintf(szBuff,128,"Mesh %u: Not suitable for vcache optimization",meshNum);
ASSIMP_LOG_WARN(szBuff);
return static_cast<ai_real>(0.f);
}
} }
// first we need to build a vertex-triangle adjacency list // first we need to build a vertex-triangle adjacency list
VertexTriangleAdjacency adj(pMesh->mFaces,pMesh->mNumFaces, pMesh->mNumVertices,true); VertexTriangleAdjacency adj(pMesh->mFaces, pMesh->mNumFaces, pMesh->mNumVertices, true);
// build a list to store per-vertex caching time stamps // build a list to store per-vertex caching time stamps
unsigned int* const piCachingStamps = new unsigned int[pMesh->mNumVertices]; std::vector<unsigned int> piCachingStamps;
memset(piCachingStamps,0x0,pMesh->mNumVertices*sizeof(unsigned int)); piCachingStamps.resize(pMesh->mNumVertices);
memset(&piCachingStamps[0], 0x0, pMesh->mNumVertices * sizeof(unsigned int));
// allocate an empty output index buffer. We store the output indices in one large array. // allocate an empty output index buffer. We store the output indices in one large array.
// Since the number of triangles won't change the input faces can be reused. This is how // Since the number of triangles won't change the input faces can be reused. This is how
// we save thousands of redundant mini allocations for aiFace::mIndices // we save thousands of redundant mini allocations for aiFace::mIndices
const unsigned int iIdxCnt = pMesh->mNumFaces*3; const unsigned int iIdxCnt = pMesh->mNumFaces * 3;
unsigned int* const piIBOutput = new unsigned int[iIdxCnt]; std::vector<unsigned int> piIBOutput;
unsigned int* piCSIter = piIBOutput; piIBOutput.resize(iIdxCnt);
std::vector<unsigned int>::iterator piCSIter = piIBOutput.begin();
// allocate the flag array to hold the information // allocate the flag array to hold the information
// whether a face has already been emitted or not // whether a face has already been emitted or not
std::vector<bool> abEmitted(pMesh->mNumFaces,false); std::vector<bool> abEmitted(pMesh->mNumFaces, false);
// dead-end vertex index stack // dead-end vertex index stack
std::stack<unsigned int, std::vector<unsigned int> > sDeadEndVStack; std::stack<unsigned int, std::vector<unsigned int>> sDeadEndVStack;
// create a copy of the piNumTriPtr buffer // create a copy of the piNumTriPtr buffer
unsigned int* const piNumTriPtr = adj.mLiveTriangles; unsigned int *const piNumTriPtr = adj.mLiveTriangles;
const std::vector<unsigned int> piNumTriPtrNoModify(piNumTriPtr, piNumTriPtr + pMesh->mNumVertices); const std::vector<unsigned int> piNumTriPtrNoModify(piNumTriPtr, piNumTriPtr + pMesh->mNumVertices);
// get the largest number of referenced triangles and allocate the "candidate buffer" // get the largest number of referenced triangles and allocate the "candidate buffer"
unsigned int iMaxRefTris = 0; { unsigned int iMaxRefTris = 0;
const unsigned int* piCur = adj.mLiveTriangles; {
const unsigned int* const piCurEnd = adj.mLiveTriangles+pMesh->mNumVertices; const unsigned int *piCur = adj.mLiveTriangles;
for (;piCur != piCurEnd;++piCur) { const unsigned int *const piCurEnd = adj.mLiveTriangles + pMesh->mNumVertices;
iMaxRefTris = std::max(iMaxRefTris,*piCur); for (; piCur != piCurEnd; ++piCur) {
iMaxRefTris = std::max(iMaxRefTris, *piCur);
} }
} }
ai_assert(iMaxRefTris > 0); ai_assert(iMaxRefTris > 0);
unsigned int* piCandidates = new unsigned int[iMaxRefTris*3]; std::vector<unsigned int> piCandidates;
piCandidates.resize(iMaxRefTris * 3);
unsigned int iCacheMisses = 0; unsigned int iCacheMisses = 0;
// ................................................................................... // ...................................................................................
@ -245,23 +254,23 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me
int ivdx = 0; int ivdx = 0;
int ics = 1; int ics = 1;
int iStampCnt = mConfigCacheDepth+1; int iStampCnt = mConfigCacheDepth + 1;
while (ivdx >= 0) { while (ivdx >= 0) {
unsigned int icnt = piNumTriPtrNoModify[ivdx]; unsigned int icnt = piNumTriPtrNoModify[ivdx];
unsigned int* piList = adj.GetAdjacentTriangles(ivdx); unsigned int *piList = adj.GetAdjacentTriangles(ivdx);
unsigned int* piCurCandidate = piCandidates; std::vector<unsigned int>::iterator piCurCandidate = piCandidates.begin();
// get all triangles in the neighborhood // get all triangles in the neighborhood
for (unsigned int tri = 0; tri < icnt;++tri) { for (unsigned int tri = 0; tri < icnt; ++tri) {
// if they have not yet been emitted, add them to the output IB // if they have not yet been emitted, add them to the output IB
const unsigned int fidx = *piList++; const unsigned int fidx = *piList++;
if (!abEmitted[fidx]) { if (!abEmitted[fidx]) {
// so iterate through all vertices of the current triangle // so iterate through all vertices of the current triangle
const aiFace* pcFace = &pMesh->mFaces[ fidx ]; const aiFace *pcFace = &pMesh->mFaces[fidx];
unsigned nind = pcFace->mNumIndices; const unsigned nind = pcFace->mNumIndices;
for (unsigned ind = 0; ind < nind; ind++) { for (unsigned ind = 0; ind < nind; ind++) {
unsigned dp = pcFace->mIndices[ind]; unsigned dp = pcFace->mIndices[ind];
@ -281,7 +290,7 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me
*piCSIter++ = dp; *piCSIter++ = dp;
// if the vertex is not yet in cache, set its cache count // if the vertex is not yet in cache, set its cache count
if (iStampCnt-piCachingStamps[dp] > mConfigCacheDepth) { if (iStampCnt - piCachingStamps[dp] > mConfigCacheDepth) {
piCachingStamps[dp] = iStampCnt++; piCachingStamps[dp] = iStampCnt++;
++iCacheMisses; ++iCacheMisses;
} }
@ -297,16 +306,16 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me
// get next fanning vertex // get next fanning vertex
ivdx = -1; ivdx = -1;
int max_priority = -1; int max_priority = -1;
for (unsigned int* piCur = piCandidates;piCur != piCurCandidate;++piCur) { for (std::vector<unsigned int>::iterator piCur = piCandidates.begin(); piCur != piCurCandidate; ++piCur) {
const unsigned int dp = *piCur; const unsigned int dp = *piCur;
// must have live triangles // must have live triangles
if (piNumTriPtr[dp] > 0) { if (piNumTriPtr[dp] > 0) {
int priority = 0; int priority = 0;
// will the vertex be in cache, even after fanning occurs? // will the vertex be in cache, even after fanning occurs?
unsigned int tmp; unsigned int tmp;
if ((tmp = iStampCnt-piCachingStamps[dp]) + 2*piNumTriPtr[dp] <= mConfigCacheDepth) { if ((tmp = iStampCnt - piCachingStamps[dp]) + 2 * piNumTriPtr[dp] <= mConfigCacheDepth) {
priority = tmp; priority = tmp;
} }
@ -324,7 +333,7 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me
while (!sDeadEndVStack.empty()) { while (!sDeadEndVStack.empty()) {
unsigned int iCachedIdx = sDeadEndVStack.top(); unsigned int iCachedIdx = sDeadEndVStack.top();
sDeadEndVStack.pop(); sDeadEndVStack.pop();
if (piNumTriPtr[ iCachedIdx ] > 0) { if (piNumTriPtr[iCachedIdx] > 0) {
ivdx = iCachedIdx; ivdx = iCachedIdx;
break; break;
} }
@ -333,9 +342,9 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me
if (-1 == ivdx) { if (-1 == ivdx) {
// well, there isn't such a vertex. Simply get the next vertex in input order and // well, there isn't such a vertex. Simply get the next vertex in input order and
// hope it is not too bad ... // hope it is not too bad ...
while (ics < (int)pMesh->mNumVertices) { while (ics < (int)pMesh->mNumVertices) {
++ics; ++ics;
if (piNumTriPtr[ics] > 0) { if (piNumTriPtr[ics] > 0) {
ivdx = ics; ivdx = ics;
break; break;
} }
@ -345,29 +354,29 @@ ai_real ImproveCacheLocalityProcess::ProcessMesh( aiMesh* pMesh, unsigned int me
} }
ai_real fACMR2 = 0.0f; ai_real fACMR2 = 0.0f;
if (!DefaultLogger::isNullLogger()) { if (!DefaultLogger::isNullLogger()) {
fACMR2 = (float)iCacheMisses / pMesh->mNumFaces; fACMR2 = static_cast<ai_real>(iCacheMisses / pMesh->mNumFaces);
const ai_real averageACMR = ((fACMR - fACMR2) / fACMR) * 100.f;
// very intense verbose logging ... prepare for much text if there are many meshes // very intense verbose logging ... prepare for much text if there are many meshes
if ( DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) { if (DefaultLogger::get()->getLogSeverity() == Logger::VERBOSE) {
ASSIMP_LOG_VERBOSE_DEBUG("Mesh %u | ACMR in: ", meshNum, " out: ", fACMR, " | ~", fACMR2, ((fACMR - fACMR2) / fACMR) * 100.f); ASSIMP_LOG_VERBOSE_DEBUG("Mesh ", meshNum, "| ACMR in: ", fACMR, " out: ", fACMR2, " | average ACMR ", averageACMR);
} }
fACMR2 *= pMesh->mNumFaces; fACMR2 *= pMesh->mNumFaces;
} }
// sort the output index buffer back to the input array
piCSIter = piIBOutput;
for (aiFace* pcFace = pMesh->mFaces; pcFace != pcEnd;++pcFace) {
unsigned nind = pcFace->mNumIndices;
unsigned * ind = pcFace->mIndices;
if (nind > 0) ind[0] = *piCSIter++;
if (nind > 1) ind[1] = *piCSIter++;
if (nind > 2) ind[2] = *piCSIter++;
}
// delete temporary storage // sort the output index buffer back to the input array
delete[] piCachingStamps; piCSIter = piIBOutput.begin();
delete[] piIBOutput; for (aiFace *pcFace = pMesh->mFaces; pcFace != pcEnd; ++pcFace) {
delete[] piCandidates; unsigned nind = pcFace->mNumIndices;
unsigned *ind = pcFace->mIndices;
if (nind > 0)
ind[0] = *piCSIter++;
if (nind > 1)
ind[1] = *piCSIter++;
if (nind > 2)
ind[2] = *piCSIter++;
}
return fACMR2; return fACMR2;
} }
} // namespace Assimp

View File

@ -290,12 +290,6 @@ void PretransformVertices::ComputeAbsoluteTransform(aiNode *pcNode) {
} }
} }
static void normalizeVectorArray(aiVector3D *vectorArrayIn, aiVector3D *vectorArrayOut, size_t numVectors) {
for (size_t i=0; i<numVectors; ++i) {
vectorArrayOut[i] = vectorArrayIn[i].Normalize();
}
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Apply the node transformation to a mesh // Apply the node transformation to a mesh
void PretransformVertices::ApplyTransform(aiMesh *mesh, const aiMatrix4x4 &mat) const { void PretransformVertices::ApplyTransform(aiMesh *mesh, const aiMatrix4x4 &mat) const {
@ -322,8 +316,11 @@ void PretransformVertices::ApplyTransform(aiMesh *mesh, const aiMatrix4x4 &mat)
const aiMatrix3x3 m = aiMatrix3x3(mat).Inverse().Transpose(); const aiMatrix3x3 m = aiMatrix3x3(mat).Inverse().Transpose();
if (mesh->HasNormals()) { if (mesh->HasNormals()) {
normalizeVectorArray(mesh->mNormals, mesh->mNormals, mesh->mNumVertices); for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
mesh->mNormals[i] = (m * mesh->mNormals[i]).Normalize();
}
} }
if (mesh->HasTangentsAndBitangents()) { if (mesh->HasTangentsAndBitangents()) {
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize(); mesh->mTangents[i] = (m * mesh->mTangents[i]).Normalize();

View File

@ -40,6 +40,9 @@
# define crc32 z_crc32 # define crc32 z_crc32
# define crc32_combine z_crc32_combine # define crc32_combine z_crc32_combine
# define crc32_combine64 z_crc32_combine64 # define crc32_combine64 z_crc32_combine64
# define crc32_combine_gen z_crc32_combine_gen
# define crc32_combine_gen64 z_crc32_combine_gen64
# define crc32_combine_op z_crc32_combine_op
# define crc32_z z_crc32_z # define crc32_z z_crc32_z
# define deflate z_deflate # define deflate z_deflate
# define deflateBound z_deflateBound # define deflateBound z_deflateBound
@ -351,6 +354,9 @@
# ifdef FAR # ifdef FAR
# undef FAR # undef FAR
# endif # endif
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# endif
# include <windows.h> # include <windows.h>
/* No need for _export, use ZLIB.DEF instead. */ /* No need for _export, use ZLIB.DEF instead. */
/* For complete Windows compatibility, use WINAPI, not __stdcall. */ /* For complete Windows compatibility, use WINAPI, not __stdcall. */
@ -469,11 +475,18 @@ typedef uLong FAR uLongf;
# undef _LARGEFILE64_SOURCE # undef _LARGEFILE64_SOURCE
#endif #endif
#if defined(__WATCOMC__) && !defined(Z_HAVE_UNISTD_H) #ifndef Z_HAVE_UNISTD_H
# define Z_HAVE_UNISTD_H # ifdef __WATCOMC__
# define Z_HAVE_UNISTD_H
# endif
#endif
#ifndef Z_HAVE_UNISTD_H
# if defined(_LARGEFILE64_SOURCE) && !defined(_WIN32)
# define Z_HAVE_UNISTD_H
# endif
#endif #endif
#ifndef Z_SOLO #ifndef Z_SOLO
# if defined(Z_HAVE_UNISTD_H) || defined(_LARGEFILE64_SOURCE) # if defined(Z_HAVE_UNISTD_H)
# include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */ # include <unistd.h> /* for SEEK_*, off_t, and _LFS64_LARGEFILE */
# ifdef VMS # ifdef VMS
# include <unixio.h> /* for off_t */ # include <unixio.h> /* for off_t */

View File

@ -63,6 +63,7 @@ struct aiImporterDesc;
namespace Assimp { namespace Assimp {
// Forward declarations
class Importer; class Importer;
class IOSystem; class IOSystem;
class BaseProcess; class BaseProcess;
@ -73,6 +74,9 @@ class IOStream;
#define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \ #define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \
(string[1] << 16) + (string[2] << 8) + string[3])) (string[1] << 16) + (string[2] << 8) + string[3]))
using UByteBuffer = std::vector<uint8_t>;
using ByteBuffer = std::vector<int8_t>;
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** FOR IMPORTER PLUGINS ONLY: The BaseImporter defines a common interface /** FOR IMPORTER PLUGINS ONLY: The BaseImporter defines a common interface
* for all importer worker classes. * for all importer worker classes.

View File

@ -70,7 +70,6 @@ namespace Assimp {
static const unsigned int BufferSize = 4096; static const unsigned int BufferSize = 4096;
// --------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------
template <class char_t> template <class char_t>
AI_FORCE_INLINE bool IsUpper(char_t in) { AI_FORCE_INLINE bool IsUpper(char_t in) {

View File

@ -1085,6 +1085,19 @@ enum aiComponent
*/ */
#define AI_CONFIG_USE_GLTF_PBR_SPECULAR_GLOSSINESS "USE_GLTF_PBR_SPECULAR_GLOSSINESS" #define AI_CONFIG_USE_GLTF_PBR_SPECULAR_GLOSSINESS "USE_GLTF_PBR_SPECULAR_GLOSSINESS"
/** @brief Specifies whether to apply a limit on the number of four bones per vertex in skinning
*
* When this flag is not defined, all bone weights and indices are limited to a
* maximum of four bones for each vertex (attributes JOINT_0 and WEIGHT_0 only).
* By enabling this flag, the number of bones per vertex is unlimited.
* In both cases, indices and bone weights are sorted by weight in descending order.
* In the case of the limit of up to four bones, a maximum of the four largest values are exported.
* Weights are not normalized.
* Property type: Bool. Default value: false.
*/
#define AI_CONFIG_EXPORT_GLTF_UNLIMITED_SKINNING_BONES_PER_VERTEX \
"USE_UNLIMITED_BONES_PER VERTEX"
/** /**
* @brief Specifies the blob name, assimp uses for exporting. * @brief Specifies the blob name, assimp uses for exporting.
* *

View File

@ -59,6 +59,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/types.h> #include <assimp/types.h>
#ifdef __cplusplus #ifdef __cplusplus
#include <unordered_set>
extern "C" { extern "C" {
#endif #endif
@ -872,11 +874,15 @@ struct aiMesh {
// DO NOT REMOVE THIS ADDITIONAL CHECK // DO NOT REMOVE THIS ADDITIONAL CHECK
if (mNumBones && mBones) { if (mNumBones && mBones) {
std::unordered_set<const aiBone *> bones;
for (unsigned int a = 0; a < mNumBones; a++) { for (unsigned int a = 0; a < mNumBones; a++) {
if (mBones[a]) { if (mBones[a]) {
delete mBones[a]; bones.insert(mBones[a]);
} }
} }
for (const aiBone *bone: bones) {
delete bone;
}
delete[] mBones; delete[] mBones;
} }

View File

@ -151,6 +151,8 @@ public:
typedef aiVector3t<ai_real> aiVector3D; typedef aiVector3t<ai_real> aiVector3D;
typedef aiVector3t<float> aiVector3f;
typedef aiVector3t<double> aiVector3d;
#else #else

View File

@ -19,6 +19,7 @@ INCLUDE_DIRECTORIES(
${Assimp_SOURCE_DIR}/include ${Assimp_SOURCE_DIR}/include
${Assimp_SOURCE_DIR}/code ${Assimp_SOURCE_DIR}/code
${SAMPLES_SHARED_CODE_DIR} ${SAMPLES_SHARED_CODE_DIR}
${Assimp_SOURCE_DIR}/contrib/utf8cpp/source
) )
LINK_DIRECTORIES( LINK_DIRECTORIES(

View File

@ -23,6 +23,7 @@
#include <dxgi1_2.h> #include <dxgi1_2.h>
#include <DirectXMath.h> #include <DirectXMath.h>
#include <d3dcompiler.h> #include <d3dcompiler.h>
#include <utf8.h>
#include "ModelLoader.h" #include "ModelLoader.h"
#include "SafeRelease.hpp" #include "SafeRelease.hpp"

View File

@ -21,6 +21,7 @@ INCLUDE_DIRECTORIES(
${OPENGL_INCLUDE_DIR} ${OPENGL_INCLUDE_DIR}
${GLUT_INCLUDE_DIR} ${GLUT_INCLUDE_DIR}
${SAMPLES_SHARED_CODE_DIR} ${SAMPLES_SHARED_CODE_DIR}
${Assimp_SOURCE_DIR}/contrib/utf8cpp/source
) )
LINK_DIRECTORIES( LINK_DIRECTORIES(

View File

@ -17,6 +17,7 @@
#include <stdio.h> #include <stdio.h>
#include <GL/gl.h> #include <GL/gl.h>
#include <GL/glu.h> #include <GL/glu.h>
#include <utf8.h>
#ifdef _MSC_VER #ifdef _MSC_VER
#pragma warning(disable: 4100) // Disable warning 'unreferenced formal parameter' #pragma warning(disable: 4100) // Disable warning 'unreferenced formal parameter'

Binary file not shown.

View File

@ -48,6 +48,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
class BlendImportAreaLight : public ::testing::Test { class BlendImportAreaLight : public ::testing::Test {
public: public:
BlendImportAreaLight() :
im(nullptr) {}
~BlendImportAreaLight() override = default;
void SetUp() override { void SetUp() override {
im = new Assimp::Importer(); im = new Assimp::Importer();
} }

View File

@ -48,11 +48,14 @@ using namespace ::Assimp;
class BlenderWorkTest : public ::testing::Test { class BlenderWorkTest : public ::testing::Test {
public: public:
virtual void SetUp() { BlenderWorkTest() : im(nullptr) {}
~BlenderWorkTest() override = default;
void SetUp() override {
im = new Assimp::Importer(); im = new Assimp::Importer();
} }
virtual void TearDown() { void TearDown() override {
delete im; delete im;
} }

Some files were not shown because too many files have changed in this diff Show More