Merge branch 'master' into M3DasciiByDefault

pull/3848/head
Kim Kulling 2021-05-12 15:31:01 +02:00 committed by GitHub
commit b70f195805
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
76 changed files with 564 additions and 536 deletions

View File

@ -527,12 +527,12 @@ ENDIF()
MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER ) MARK_AS_ADVANCED ( ASSIMP_BUILD_ARCHITECTURE ASSIMP_BUILD_COMPILER )
SET ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER OFF CACHE BOOL SET ( ASSIMP_BUILD_NONFREE_C4D_IMPORTER OFF CACHE BOOL
"Build the C4D importer, which relies on the non-free Melange SDK." "Build the C4D importer, which relies on the non-free Cineware SDK."
) )
IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER) IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
IF ( MSVC ) IF ( MSVC )
SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/includes") SET(C4D_INCLUDES "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/includes")
# pick the correct prebuilt library # pick the correct prebuilt library
IF(MSVC15) IF(MSVC15)
@ -551,22 +551,23 @@ IF (ASSIMP_BUILD_NONFREE_C4D_IMPORTER)
) )
ENDIF() ENDIF()
SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Melange/libraries/win") SET(C4D_LIB_BASE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/contrib/Cineware/libraries/win")
SET(C4D_DEBUG_LIBRARIES SET(C4D_DEBUG_LIBRARIES
"${C4D_LIB_BASE_PATH}/melangelib${C4D_LIB_POSTFIX}/melangelib_debug.lib" "${C4D_LIB_BASE_PATH}/cinewarelib${C4D_LIB_POSTFIX}/cinewarelib_debug.lib"
"${C4D_LIB_BASE_PATH}/jpeglib${C4D_LIB_POSTFIX}/jpeglib_debug.lib" "${C4D_LIB_BASE_PATH}/jpeglib${C4D_LIB_POSTFIX}/jpeglib_debug.lib"
) )
SET(C4D_RELEASE_LIBRARIES SET(C4D_RELEASE_LIBRARIES
"${C4D_LIB_BASE_PATH}/melangelib${C4D_LIB_POSTFIX}/melangelib_release.lib" "${C4D_LIB_BASE_PATH}/cinewarelib${C4D_LIB_POSTFIX}/cinewarelib_release.lib"
"${C4D_LIB_BASE_PATH}/jpeglib${C4D_LIB_POSTFIX}/jpeglib_release.lib" "${C4D_LIB_BASE_PATH}/jpeglib${C4D_LIB_POSTFIX}/jpeglib_release.lib"
) )
# winsock and winmm are necessary dependencies of melange (this is undocumented, but true.) # winsock and winmm are necessary (and undocumented) dependencies of Cineware SDK because
# it can be used to communicate with a running Cinema 4D instance
SET(C4D_EXTRA_LIBRARIES WSock32.lib Winmm.lib) SET(C4D_EXTRA_LIBRARIES WSock32.lib Winmm.lib)
ELSE () ELSE ()
MESSAGE( FATAL_ERROR MESSAGE( FATAL_ERROR
"C4D is currently only available on Windows with melange SDK installed in contrib/Melange" "C4D is currently only available on Windows with Cineware SDK installed in contrib/Cineware"
) )
ENDIF () ENDIF ()
ELSE () ELSE ()

View File

@ -69,7 +69,7 @@ void Discreet3DSImporter::ReplaceDefaultMaterial() {
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 (std::string::iterator it = s.begin(); it != s.end(); ++it) { for (std::string::iterator it = s.begin(); it != s.end(); ++it) {
*it = static_cast<char>(::tolower(*it)); *it = static_cast<char>(::tolower(static_cast<unsigned char>(*it)));
} }
if (std::string::npos == s.find("default")) continue; if (std::string::npos == s.find("default")) continue;

View File

@ -102,13 +102,14 @@ private:
// preserves the mesh's given name if it has one. |index| is the index // preserves the mesh's given name if it has one. |index| is the index
// of the mesh in |aiScene::mMeshes|. // of the mesh in |aiScene::mMeshes|.
std::string GetMeshName(const aiMesh &mesh, unsigned int index, const aiNode &node) { std::string GetMeshName(const aiMesh &mesh, unsigned int index, const aiNode &node) {
static const std::string underscore = "_"; static const char underscore = '_';
char postfix[10] = { 0 }; char postfix[10] = { 0 };
ASSIMP_itoa10(postfix, index); ASSIMP_itoa10(postfix, index);
std::string result = node.mName.C_Str(); std::string result = node.mName.C_Str();
if (mesh.mName.length > 0) { if (mesh.mName.length > 0) {
result += underscore + mesh.mName.C_Str(); result += underscore;
result += mesh.mName.C_Str();
} }
return result + underscore + postfix; return result + underscore + postfix;
} }

View File

@ -61,20 +61,10 @@ namespace D3DS {
#include <assimp/Compiler/pushpack1.h> #include <assimp/Compiler/pushpack1.h>
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Discreet3DS class: Helper class for loading 3ds files. Defines chunks /** Defines chunks and data structures.
* and data structures.
*/ */
class Discreet3DS { namespace Discreet3DS {
private:
Discreet3DS() AI_NO_EXCEPT {
// empty
}
~Discreet3DS() {
// empty
}
public:
//! data structure for a single chunk in a .3ds file //! data structure for a single chunk in a .3ds file
struct Chunk { struct Chunk {
uint16_t Flag; uint16_t Flag;
@ -314,7 +304,7 @@ public:
// camera sub-chunks // camera sub-chunks
CHUNK_CAM_RANGES = 0x4720 CHUNK_CAM_RANGES = 0x4720
}; };
}; }
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
/** Helper structure representing a 3ds mesh face */ /** Helper structure representing a 3ds mesh face */

View File

@ -143,7 +143,13 @@ void Discreet3DSImporter::SetupProperties(const Importer * /*pImp*/) {
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void Discreet3DSImporter::InternReadFile(const std::string &pFile, void Discreet3DSImporter::InternReadFile(const std::string &pFile,
aiScene *pScene, IOSystem *pIOHandler) { aiScene *pScene, IOSystem *pIOHandler) {
StreamReaderLE theStream(pIOHandler->Open(pFile, "rb"));
auto theFile = pIOHandler->Open(pFile, "rb");
if (!theFile) {
throw DeadlyImportError("3DS: Could not open ", pFile);
}
StreamReaderLE theStream(theFile);
// We should have at least one chunk // We should have at least one chunk
if (theStream.GetRemainingSize() < 16) { if (theStream.GetRemainingSize() < 16) {
@ -981,9 +987,9 @@ void Discreet3DSImporter::ParseMeshChunk() {
mMesh.mMat.a3 = stream->GetF4(); mMesh.mMat.a3 = stream->GetF4();
mMesh.mMat.b3 = stream->GetF4(); mMesh.mMat.b3 = stream->GetF4();
mMesh.mMat.c3 = stream->GetF4(); mMesh.mMat.c3 = stream->GetF4();
mMesh.mMat.d1 = stream->GetF4(); mMesh.mMat.a4 = stream->GetF4();
mMesh.mMat.d2 = stream->GetF4(); mMesh.mMat.b4 = stream->GetF4();
mMesh.mMat.d3 = stream->GetF4(); mMesh.mMat.c4 = stream->GetF4();
} break; } break;
case Discreet3DS::CHUNK_MAPLIST: { case Discreet3DS::CHUNK_MAPLIST: {

View File

@ -44,63 +44,66 @@ namespace Assimp {
namespace D3MF { namespace D3MF {
namespace XmlTag { namespace XmlTag {
// Root tag
const char* const RootTag = "3MF";
// Meta-data // Meta-data
static const std::string meta = "metadata"; const char* const meta = "metadata";
static const std::string meta_name = "name"; const char* const meta_name = "name";
// Model-data specific tags // Model-data specific tags
static const std::string model = "model"; const char* const model = "model";
static const std::string model_unit = "unit"; const char* const model_unit = "unit";
static const std::string metadata = "metadata"; const char* const metadata = "metadata";
static const std::string resources = "resources"; const char* const resources = "resources";
static const std::string object = "object"; const char* const object = "object";
static const std::string mesh = "mesh"; const char* const mesh = "mesh";
static const std::string components = "components"; const char* const components = "components";
static const std::string component = "component"; const char* const component = "component";
static const std::string vertices = "vertices"; const char* const vertices = "vertices";
static const std::string vertex = "vertex"; const char* const vertex = "vertex";
static const std::string triangles = "triangles"; const char* const triangles = "triangles";
static const std::string triangle = "triangle"; const char* const triangle = "triangle";
static const std::string x = "x"; const char* const x = "x";
static const std::string y = "y"; const char* const y = "y";
static const std::string z = "z"; const char* const z = "z";
static const std::string v1 = "v1"; const char* const v1 = "v1";
static const std::string v2 = "v2"; const char* const v2 = "v2";
static const std::string v3 = "v3"; const char* const v3 = "v3";
static const std::string id = "id"; const char* const id = "id";
static const std::string pid = "pid"; const char* const pid = "pid";
static const std::string pindex = "pindex"; const char* const pindex = "pindex";
static const std::string p1 = "p1"; const char* const p1 = "p1";
static const std::string name = "name"; const char* const name = "name";
static const std::string type = "type"; const char* const type = "type";
static const std::string build = "build"; const char* const build = "build";
static const std::string item = "item"; const char* const item = "item";
static const std::string objectid = "objectid"; const char* const objectid = "objectid";
static const std::string transform = "transform"; const char* const transform = "transform";
// Material definitions // Material definitions
static const std::string basematerials = "basematerials"; const char* const basematerials = "basematerials";
static const std::string basematerials_id = "id"; const char* const basematerials_id = "id";
static const std::string basematerials_base = "base"; const char* const basematerials_base = "base";
static const std::string basematerials_name = "name"; const char* const basematerials_name = "name";
static const std::string basematerials_displaycolor = "displaycolor"; const char* const basematerials_displaycolor = "displaycolor";
// Meta info tags // Meta info tags
static const std::string CONTENT_TYPES_ARCHIVE = "[Content_Types].xml"; const char* const CONTENT_TYPES_ARCHIVE = "[Content_Types].xml";
static const std::string ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels"; const char* const ROOT_RELATIONSHIPS_ARCHIVE = "_rels/.rels";
static const std::string SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types"; const char* const SCHEMA_CONTENTTYPES = "http://schemas.openxmlformats.org/package/2006/content-types";
static const std::string SCHEMA_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships"; const char* const SCHEMA_RELATIONSHIPS = "http://schemas.openxmlformats.org/package/2006/relationships";
static const std::string RELS_RELATIONSHIP_CONTAINER = "Relationships"; const char* const RELS_RELATIONSHIP_CONTAINER = "Relationships";
static const std::string RELS_RELATIONSHIP_NODE = "Relationship"; const char* const RELS_RELATIONSHIP_NODE = "Relationship";
static const std::string RELS_ATTRIB_TARGET = "Target"; const char* const RELS_ATTRIB_TARGET = "Target";
static const std::string RELS_ATTRIB_TYPE = "Type"; const char* const RELS_ATTRIB_TYPE = "Type";
static const std::string RELS_ATTRIB_ID = "Id"; const char* const RELS_ATTRIB_ID = "Id";
static const std::string PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel"; const char* const PACKAGE_START_PART_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dmodel";
static const std::string PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket"; const char* const PACKAGE_PRINT_TICKET_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/printticket";
static const std::string PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture"; const char* const PACKAGE_TEXTURE_RELATIONSHIP_TYPE = "http://schemas.microsoft.com/3dmanufacturing/2013/01/3dtexture";
static const std::string PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; const char* const PACKAGE_CORE_PROPERTIES_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
static const std::string PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail"; const char* const PACKAGE_THUMBNAIL_RELATIONSHIP_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/thumbnail";
} }
} // Namespace D3MF } // Namespace D3MF
} // Namespace Assimp } // Namespace Assimp

View File

@ -307,18 +307,26 @@ void D3MFExporter::writeMesh(aiMesh *mesh) {
return; return;
} }
mModelOutput << "<" << XmlTag::mesh << ">" << std::endl; mModelOutput << "<"
mModelOutput << "<" << XmlTag::vertices << ">" << std::endl; << XmlTag::mesh
<< ">" << "\n";
mModelOutput << "<"
<< XmlTag::vertices
<< ">" << "\n";
for (unsigned int i = 0; i < mesh->mNumVertices; ++i) { for (unsigned int i = 0; i < mesh->mNumVertices; ++i) {
writeVertex(mesh->mVertices[i]); writeVertex(mesh->mVertices[i]);
} }
mModelOutput << "</" << XmlTag::vertices << ">" << std::endl; mModelOutput << "</"
<< XmlTag::vertices << ">"
<< "\n";
const unsigned int matIdx(mesh->mMaterialIndex); const unsigned int matIdx(mesh->mMaterialIndex);
writeFaces(mesh, matIdx); writeFaces(mesh, matIdx);
mModelOutput << "</" << XmlTag::mesh << ">" << std::endl; mModelOutput << "</"
<< XmlTag::mesh << ">"
<< "\n";
} }
void D3MFExporter::writeVertex(const aiVector3D &pos) { void D3MFExporter::writeVertex(const aiVector3D &pos) {
@ -334,27 +342,34 @@ void D3MFExporter::writeFaces(aiMesh *mesh, unsigned int matIdx) {
if (!mesh->HasFaces()) { if (!mesh->HasFaces()) {
return; return;
} }
mModelOutput << "<" << XmlTag::triangles << ">" << std::endl; mModelOutput << "<"
<< XmlTag::triangles << ">"
<< "\n";
for (unsigned int i = 0; i < mesh->mNumFaces; ++i) { for (unsigned int i = 0; i < mesh->mNumFaces; ++i) {
aiFace &currentFace = mesh->mFaces[i]; aiFace &currentFace = mesh->mFaces[i];
mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[0] << "\" v2=\"" mModelOutput << "<" << XmlTag::triangle << " v1=\"" << currentFace.mIndices[0] << "\" v2=\""
<< currentFace.mIndices[1] << "\" v3=\"" << currentFace.mIndices[2] << currentFace.mIndices[1] << "\" v3=\"" << currentFace.mIndices[2]
<< "\" pid=\"1\" p1=\"" + ai_to_string(matIdx) + "\" />"; << "\" pid=\"1\" p1=\"" + ai_to_string(matIdx) + "\" />";
mModelOutput << std::endl; mModelOutput << "\n";
} }
mModelOutput << "</" << XmlTag::triangles << ">"; mModelOutput << "</"
mModelOutput << std::endl; << XmlTag::triangles
<< ">";
mModelOutput << "\n";
} }
void D3MFExporter::writeBuild() { void D3MFExporter::writeBuild() {
mModelOutput << "<" << XmlTag::build << ">" << std::endl; mModelOutput << "<"
<< XmlTag::build
<< ">"
<< "\n";
for (size_t i = 0; i < mBuildItems.size(); ++i) { for (size_t i = 0; i < mBuildItems.size(); ++i) {
mModelOutput << "<" << XmlTag::item << " objectid=\"" << i + 2 << "\"/>"; mModelOutput << "<" << XmlTag::item << " objectid=\"" << i + 2 << "\"/>";
mModelOutput << std::endl; mModelOutput << "\n";
} }
mModelOutput << "</" << XmlTag::build << ">"; mModelOutput << "</" << XmlTag::build << ">";
mModelOutput << std::endl; mModelOutput << "\n";
} }
void D3MFExporter::zipContentType(const std::string &filename) { void D3MFExporter::zipContentType(const std::string &filename) {

View File

@ -42,6 +42,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_3MF_IMPORTER #ifndef ASSIMP_BUILD_NO_3MF_IMPORTER
#include "D3MFImporter.h" #include "D3MFImporter.h"
#include "3MFXmlTags.h"
#include "D3MFOpcPackage.h"
#include <assimp/StringComparison.h> #include <assimp/StringComparison.h>
#include <assimp/StringUtils.h> #include <assimp/StringUtils.h>
@ -51,17 +53,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/fast_atof.h>
#include <cassert> #include <cassert>
#include <map> #include <map>
#include <memory> #include <memory>
#include <string> #include <string>
#include <vector> #include <vector>
#include "3MFXmlTags.h"
#include "D3MFOpcPackage.h"
#include <assimp/fast_atof.h>
#include <iomanip> #include <iomanip>
#include <string.h>
namespace Assimp { namespace Assimp {
namespace D3MF { namespace D3MF {
@ -72,32 +72,39 @@ enum class ResourceType {
RT_Unknown RT_Unknown
}; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...) }; // To be extended with other resource types (eg. material extension resources like Texture2d, Texture2dGroup...)
class Resource class Resource {
{
public: public:
Resource(int id) :
mId(id) {}
virtual ~Resource() {}
int mId; int mId;
virtual ResourceType getType() { Resource(int id) :
mId(id) {
// empty
}
virtual ~Resource() {
// empty
}
virtual ResourceType getType() const {
return ResourceType::RT_Unknown; return ResourceType::RT_Unknown;
} }
}; };
class BaseMaterials : public Resource { class BaseMaterials : public Resource {
public: public:
BaseMaterials(int id) :
Resource(id),
mMaterials(),
mMaterialIndex() {}
std::vector<aiMaterial *> mMaterials; std::vector<aiMaterial *> mMaterials;
std::vector<unsigned int> mMaterialIndex; std::vector<unsigned int> mMaterialIndex;
virtual ResourceType getType() { BaseMaterials(int id) :
Resource(id),
mMaterials(),
mMaterialIndex() {
// empty
}
~BaseMaterials() = default;
ResourceType getType() const override {
return ResourceType::RT_BaseMaterials; return ResourceType::RT_BaseMaterials;
} }
}; };
@ -109,24 +116,26 @@ struct Component {
class Object : public Resource { class Object : public Resource {
public: public:
std::vector<aiMesh*> mMeshes; std::vector<aiMesh *> mMeshes;
std::vector<unsigned int> mMeshIndex; std::vector<unsigned int> mMeshIndex;
std::vector<Component> mComponents; std::vector<Component> mComponents;
std::string mName; std::string mName;
Object(int id) : Object(int id) :
Resource(id), Resource(id),
mName(std::string("Object_") + ai_to_string(id)) {} mName(std::string("Object_") + ai_to_string(id)) {
// empty
}
virtual ResourceType getType() { ~Object() = default;
ResourceType getType() const override {
return ResourceType::RT_Object; return ResourceType::RT_Object;
} }
}; };
class XmlSerializer { class XmlSerializer {
public: public:
XmlSerializer(XmlParser *xmlParser) : XmlSerializer(XmlParser *xmlParser) :
mResourcesDictionnary(), mResourcesDictionnary(),
mMaterialCount(0), mMaterialCount(0),
@ -136,7 +145,7 @@ public:
} }
~XmlSerializer() { ~XmlSerializer() {
for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) { for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it ) {
delete it->second; delete it->second;
} }
} }
@ -146,28 +155,28 @@ public:
return; return;
} }
scene->mRootNode = new aiNode("3MF"); scene->mRootNode = new aiNode(XmlTag::RootTag);
XmlNode node = mXmlParser->getRootNode().child("model"); XmlNode node = mXmlParser->getRootNode().child(XmlTag::model);
if (node.empty()) { if (node.empty()) {
return; return;
} }
XmlNode resNode = node.child("resources"); XmlNode resNode = node.child(XmlTag::resources);
for (XmlNode currentNode = resNode.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (auto &currentNode : resNode.children()) {
const std::string &currentNodeName = currentNode.name(); const std::string currentNodeName = currentNode.name();
if (currentNodeName == D3MF::XmlTag::object) { if (currentNodeName == XmlTag::object) {
ReadObject(currentNode);; ReadObject(currentNode);
} else if (currentNodeName == D3MF::XmlTag::basematerials) { } else if (currentNodeName == XmlTag::basematerials) {
ReadBaseMaterials(currentNode); ReadBaseMaterials(currentNode);
} else if (currentNodeName == D3MF::XmlTag::meta) { } else if (currentNodeName == XmlTag::meta) {
ReadMetadata(currentNode); ReadMetadata(currentNode);
} }
} }
XmlNode buildNode = node.child("build"); XmlNode buildNode = node.child(XmlTag::build);
for (XmlNode currentNode = buildNode.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (auto &currentNode : buildNode.children()) {
const std::string &currentNodeName = currentNode.name(); const std::string currentNodeName = currentNode.name();
if (currentNodeName == D3MF::XmlTag::item) { if (currentNodeName == XmlTag::item) {
int objectId = -1; int objectId = -1;
std::string transformationMatrixStr; std::string transformationMatrixStr;
aiMatrix4x4 transformationMatrix; aiMatrix4x4 transformationMatrix;
@ -186,10 +195,9 @@ public:
} }
} }
// import the metadata // import the metadata
if (!mMetaData.empty()) { if (!mMetaData.empty()) {
const size_t numMeta(mMetaData.size()); const size_t numMeta = mMetaData.size();
scene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta)); scene->mMetaData = aiMetadata::Alloc(static_cast<unsigned int>(numMeta));
for (size_t i = 0; i < numMeta; ++i) { for (size_t i = 0; i < numMeta; ++i) {
aiString val(mMetaData[i].value); aiString val(mMetaData[i].value);
@ -201,22 +209,22 @@ public:
scene->mNumMeshes = static_cast<unsigned int>(mMeshCount); scene->mNumMeshes = static_cast<unsigned int>(mMeshCount);
if (scene->mNumMeshes != 0) { if (scene->mNumMeshes != 0) {
scene->mMeshes = new aiMesh *[scene->mNumMeshes](); scene->mMeshes = new aiMesh *[scene->mNumMeshes]();
for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) { for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) {
if (it->second->getType() == ResourceType::RT_Object) { if (it->second->getType() == ResourceType::RT_Object) {
Object *obj = static_cast<Object*>(it->second); Object *obj = static_cast<Object *>(it->second);
ai_assert(nullptr != obj);
for (unsigned int i = 0; i < obj->mMeshes.size(); ++i) { for (unsigned int i = 0; i < obj->mMeshes.size(); ++i) {
scene->mMeshes[obj->mMeshIndex[i]] = obj->mMeshes[i]; scene->mMeshes[obj->mMeshIndex[i]] = obj->mMeshes[i];
} }
} }
} }
} }
// import the materials // import the materials
scene->mNumMaterials = static_cast<unsigned int>(mMaterialCount); scene->mNumMaterials = mMaterialCount;
if (scene->mNumMaterials != 0) { if (scene->mNumMaterials != 0) {
scene->mMaterials = new aiMaterial *[scene->mNumMaterials]; scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); it++) { for (auto it = mResourcesDictionnary.begin(); it != mResourcesDictionnary.end(); ++it) {
if (it->second->getType() == ResourceType::RT_BaseMaterials) { if (it->second->getType() == ResourceType::RT_BaseMaterials) {
BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second); BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
for (unsigned int i = 0; i < baseMaterials->mMaterials.size(); ++i) { for (unsigned int i = 0; i < baseMaterials->mMaterials.size(); ++i) {
@ -228,35 +236,36 @@ public:
} }
private: private:
void addObjectToNode(aiNode *parent, Object *obj, aiMatrix4x4 nodeTransform) {
ai_assert(nullptr != obj);
void addObjectToNode(aiNode* parent, Object* obj, aiMatrix4x4 nodeTransform) {
aiNode *sceneNode = new aiNode(obj->mName); aiNode *sceneNode = new aiNode(obj->mName);
sceneNode->mNumMeshes = static_cast<unsigned int>(obj->mMeshes.size()); sceneNode->mNumMeshes = static_cast<unsigned int>(obj->mMeshes.size());
sceneNode->mMeshes = new unsigned int[sceneNode->mNumMeshes]; sceneNode->mMeshes = new unsigned int[sceneNode->mNumMeshes];
std::copy(obj->mMeshIndex.begin(), obj->mMeshIndex.end(), sceneNode->mMeshes); std::copy(obj->mMeshIndex.begin(), obj->mMeshIndex.end(), sceneNode->mMeshes);
sceneNode->mTransformation = nodeTransform; sceneNode->mTransformation = nodeTransform;
if (nullptr != parent) {
parent->addChildren(1, &sceneNode); parent->addChildren(1, &sceneNode);
}
for (size_t i = 0; i < obj->mComponents.size(); ++i) { for (size_t i = 0; i < obj->mComponents.size(); ++i) {
Component c = obj->mComponents[i]; Component c = obj->mComponents[i];
auto it = mResourcesDictionnary.find(c.mObjectId); auto it = mResourcesDictionnary.find(c.mObjectId);
if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) { if (it != mResourcesDictionnary.end() && it->second->getType() == ResourceType::RT_Object) {
addObjectToNode(sceneNode, static_cast<Object*>(it->second), c.mTransformation); addObjectToNode(sceneNode, static_cast<Object *>(it->second), c.mTransformation);
} }
} }
} }
bool getNodeAttribute(const XmlNode& node, const std::string& attribute, std::string& value) { bool getNodeAttribute(const XmlNode &node, const std::string &attribute, std::string &value) {
pugi::xml_attribute objectAttribute = node.attribute(attribute.c_str()); pugi::xml_attribute objectAttribute = node.attribute(attribute.c_str());
if (!objectAttribute.empty()) { if (!objectAttribute.empty()) {
value = objectAttribute.as_string(); value = objectAttribute.as_string();
return true; return true;
} else {
return false;
} }
return false;
} }
bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &value) { bool getNodeAttribute(const XmlNode &node, const std::string &attribute, int &value) {
@ -265,9 +274,9 @@ private:
if (ret) { if (ret) {
value = std::atoi(strValue.c_str()); value = std::atoi(strValue.c_str());
return true; return true;
} else { }
return false;
} return false;
} }
aiMatrix4x4 parseTransformMatrix(std::string matrixStr) { aiMatrix4x4 parseTransformMatrix(std::string matrixStr) {
@ -287,7 +296,7 @@ private:
} }
} }
if (currentNumber.size() > 0) { if (currentNumber.size() > 0) {
float f = std::stof(currentNumber); const float f = std::stof(currentNumber);
numbers.push_back(f); numbers.push_back(f);
} }
@ -311,29 +320,26 @@ private:
transformMatrix.b4 = numbers[10]; transformMatrix.b4 = numbers[10];
transformMatrix.c4 = numbers[11]; transformMatrix.c4 = numbers[11];
transformMatrix.d4 = 1; transformMatrix.d4 = 1;
return transformMatrix; return transformMatrix;
} }
void ReadObject(XmlNode &node) { void ReadObject(XmlNode &node) {
int id = -1, pid = -1, pindex = -1; int id = -1, pid = -1, pindex = -1;
bool hasId = getNodeAttribute(node, D3MF::XmlTag::id, id); bool hasId = getNodeAttribute(node, XmlTag::id, id);
//bool hasType = getNodeAttribute(node, D3MF::XmlTag::type, type); not used currently bool hasPid = getNodeAttribute(node, XmlTag::pid, pid);
bool hasPid = getNodeAttribute(node, D3MF::XmlTag::pid, pid); bool hasPindex = getNodeAttribute(node, XmlTag::pindex, pindex);
bool hasPindex = getNodeAttribute(node, D3MF::XmlTag::pindex, pindex);
std::string idStr = ai_to_string(id);
if (!hasId) { if (!hasId) {
return; return;
} }
Object *obj = new Object(id); Object *obj = new Object(id);
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string &currentName = currentNode.name();
if (currentName == D3MF::XmlTag::mesh) { if (currentName == D3MF::XmlTag::mesh) {
auto mesh = ReadMesh(currentNode); auto mesh = ReadMesh(currentNode);
mesh->mName.Set(idStr); mesh->mName.Set(ai_to_string(id));
if (hasPid) { if (hasPid) {
auto it = mResourcesDictionnary.find(pid); auto it = mResourcesDictionnary.find(pid);
@ -347,8 +353,9 @@ private:
obj->mMeshIndex.push_back(mMeshCount); obj->mMeshIndex.push_back(mMeshCount);
mMeshCount++; mMeshCount++;
} else if (currentName == D3MF::XmlTag::components) { } else if (currentName == D3MF::XmlTag::components) {
for (XmlNode currentSubNode = currentNode.first_child(); currentSubNode; currentSubNode = currentSubNode.next_sibling()) { for (XmlNode &currentSubNode : currentNode.children()) {
if (currentSubNode.name() == D3MF::XmlTag::component) { const std::string subNodeName = currentSubNode.name();
if (subNodeName == D3MF::XmlTag::component) {
int objectId = -1; int objectId = -1;
std::string componentTransformStr; std::string componentTransformStr;
aiMatrix4x4 componentTransform; aiMatrix4x4 componentTransform;
@ -356,8 +363,9 @@ private:
componentTransform = parseTransformMatrix(componentTransformStr); componentTransform = parseTransformMatrix(componentTransformStr);
} }
if (getNodeAttribute(currentSubNode, D3MF::XmlTag::objectid, objectId)) if (getNodeAttribute(currentSubNode, D3MF::XmlTag::objectid, objectId)) {
obj->mComponents.push_back({ objectId, componentTransform }); obj->mComponents.push_back({ objectId, componentTransform });
}
} }
} }
} }
@ -369,21 +377,20 @@ private:
aiMesh *ReadMesh(XmlNode &node) { aiMesh *ReadMesh(XmlNode &node) {
aiMesh *mesh = new aiMesh(); aiMesh *mesh = new aiMesh();
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string currentName = currentNode.name();
if (currentName == D3MF::XmlTag::vertices) { if (currentName == XmlTag::vertices) {
ImportVertices(currentNode, mesh); ImportVertices(currentNode, mesh);
} else if (currentName == D3MF::XmlTag::triangles) { } else if (currentName == XmlTag::triangles) {
ImportTriangles(currentNode, mesh); ImportTriangles(currentNode, mesh);
} }
} }
return mesh; return mesh;
} }
void ReadMetadata(XmlNode &node) { void ReadMetadata(XmlNode &node) {
pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name.c_str()); pugi::xml_attribute attribute = node.attribute(D3MF::XmlTag::meta_name);
const std::string name = attribute.as_string(); const std::string name = attribute.as_string();
const std::string value = node.value(); const std::string value = node.value();
if (name.empty()) { if (name.empty()) {
@ -398,9 +405,9 @@ private:
void ImportVertices(XmlNode &node, aiMesh *mesh) { void ImportVertices(XmlNode &node, aiMesh *mesh) {
std::vector<aiVector3D> vertices; std::vector<aiVector3D> vertices;
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string currentName = currentNode.name();
if (currentName == D3MF::XmlTag::vertex) { if (currentName == XmlTag::vertex) {
vertices.push_back(ReadVertex(currentNode)); vertices.push_back(ReadVertex(currentNode));
} }
} }
@ -412,29 +419,28 @@ private:
aiVector3D ReadVertex(XmlNode &node) { aiVector3D ReadVertex(XmlNode &node) {
aiVector3D vertex; aiVector3D vertex;
vertex.x = ai_strtof(node.attribute(D3MF::XmlTag::x.c_str()).as_string(), nullptr); vertex.x = ai_strtof(node.attribute(XmlTag::x).as_string(), nullptr);
vertex.y = ai_strtof(node.attribute(D3MF::XmlTag::y.c_str()).as_string(), nullptr); vertex.y = ai_strtof(node.attribute(XmlTag::y).as_string(), nullptr);
vertex.z = ai_strtof(node.attribute(D3MF::XmlTag::z.c_str()).as_string(), nullptr); vertex.z = ai_strtof(node.attribute(XmlTag::z).as_string(), nullptr);
return vertex; return vertex;
} }
void ImportTriangles(XmlNode &node, aiMesh *mesh) { void ImportTriangles(XmlNode &node, aiMesh *mesh) {
std::vector<aiFace> faces; std::vector<aiFace> faces;
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) { for (XmlNode &currentNode : node.children()) {
const std::string &currentName = currentNode.name(); const std::string currentName = currentNode.name();
if (currentName == D3MF::XmlTag::triangle) { if (currentName == XmlTag::triangle) {
aiFace face = ReadTriangle(currentNode); aiFace face = ReadTriangle(currentNode);
faces.push_back(face); faces.push_back(face);
int pid = 0, p1; int pid = 0, p1 = 0;
bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid); bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1); bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1);
if (hasPid && hasP1) { if (hasPid && hasP1) {
auto it = mResourcesDictionnary.find(pid); auto it = mResourcesDictionnary.find(pid);
if (it != mResourcesDictionnary.end()) if (it != mResourcesDictionnary.end()) {
{
if (it->second->getType() == ResourceType::RT_BaseMaterials) { if (it->second->getType() == ResourceType::RT_BaseMaterials) {
BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second); BaseMaterials *baseMaterials = static_cast<BaseMaterials *>(it->second);
mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1]; mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
@ -457,9 +463,9 @@ private:
face.mNumIndices = 3; face.mNumIndices = 3;
face.mIndices = new unsigned int[face.mNumIndices]; face.mIndices = new unsigned int[face.mNumIndices];
face.mIndices[0] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v1.c_str()).as_string())); face.mIndices[0] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v1).as_string()));
face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v2.c_str()).as_string())); face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v2).as_string()));
face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(D3MF::XmlTag::v3.c_str()).as_string())); face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string()));
return face; return face;
} }
@ -467,14 +473,14 @@ private:
void ReadBaseMaterials(XmlNode &node) { void ReadBaseMaterials(XmlNode &node) {
int id = -1; int id = -1;
if (getNodeAttribute(node, D3MF::XmlTag::basematerials_id, id)) { if (getNodeAttribute(node, D3MF::XmlTag::basematerials_id, id)) {
BaseMaterials* baseMaterials = new BaseMaterials(id); BaseMaterials *baseMaterials = new BaseMaterials(id);
for (XmlNode currentNode = node.first_child(); currentNode; currentNode = currentNode.next_sibling()) for (XmlNode &currentNode : node.children()) {
{ const std::string currentName = currentNode.name();
if (currentNode.name() == D3MF::XmlTag::basematerials_base) { if (currentName == XmlTag::basematerials_base) {
baseMaterials->mMaterialIndex.push_back(mMaterialCount); baseMaterials->mMaterialIndex.push_back(mMaterialCount);
baseMaterials->mMaterials.push_back(readMaterialDef(currentNode, id)); baseMaterials->mMaterials.push_back(readMaterialDef(currentNode, id));
mMaterialCount++; ++mMaterialCount;
} }
} }
@ -488,7 +494,7 @@ private:
} }
//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)
const size_t len(strlen(color)); const size_t len = strlen(color);
if (9 != len && 7 != len) { if (9 != len && 7 != len) {
return false; return false;
} }
@ -517,7 +523,7 @@ private:
} }
void assignDiffuseColor(XmlNode &node, aiMaterial *mat) { void assignDiffuseColor(XmlNode &node, aiMaterial *mat) {
const char *color = node.attribute(D3MF::XmlTag::basematerials_displaycolor.c_str()).as_string(); const char *color = node.attribute(XmlTag::basematerials_displaycolor).as_string();
aiColor4D diffuse; aiColor4D diffuse;
if (parseColor(color, diffuse)) { if (parseColor(color, diffuse)) {
mat->AddProperty<aiColor4D>(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE); mat->AddProperty<aiColor4D>(&diffuse, 1, AI_MATKEY_COLOR_DIFFUSE);
@ -531,7 +537,7 @@ private:
bool hasName = getNodeAttribute(node, D3MF::XmlTag::basematerials_name, name); bool hasName = getNodeAttribute(node, D3MF::XmlTag::basematerials_name, name);
std::string stdMaterialName; std::string stdMaterialName;
std::string strId(ai_to_string(basematerialsId)); const std::string strId(ai_to_string(basematerialsId));
stdMaterialName += "id"; stdMaterialName += "id";
stdMaterialName += strId; stdMaterialName += strId;
stdMaterialName += "_"; stdMaterialName += "_";
@ -556,13 +562,15 @@ private:
std::string value; std::string value;
}; };
std::vector<MetaEntry> mMetaData; std::vector<MetaEntry> mMetaData;
std::map<unsigned int, Resource*> mResourcesDictionnary; std::map<unsigned int, Resource *> mResourcesDictionnary;
unsigned int mMaterialCount, mMeshCount; unsigned int mMaterialCount, mMeshCount;
XmlParser *mXmlParser; XmlParser *mXmlParser;
}; };
} //namespace D3MF } //namespace D3MF
using namespace D3MF;
static const aiImporterDesc desc = { static const aiImporterDesc desc = {
"3mf Importer", "3mf Importer",
"", "",
@ -596,7 +604,7 @@ bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bo
if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) { if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) {
return false; return false;
} }
D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename); D3MFOpcPackage opcPackage(pIOHandler, filename);
return opcPackage.validate(); return opcPackage.validate();
} }
@ -612,11 +620,11 @@ const aiImporterDesc *D3MFImporter::GetInfo() const {
} }
void D3MFImporter::InternReadFile(const std::string &filename, aiScene *pScene, IOSystem *pIOHandler) { void D3MFImporter::InternReadFile(const std::string &filename, aiScene *pScene, IOSystem *pIOHandler) {
D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename); D3MFOpcPackage opcPackage(pIOHandler, filename);
XmlParser xmlParser; XmlParser xmlParser;
if (xmlParser.parse(opcPackage.RootStream())) { if (xmlParser.parse(opcPackage.RootStream())) {
D3MF::XmlSerializer xmlSerializer(&xmlParser); XmlSerializer xmlSerializer(&xmlParser);
xmlSerializer.ImportXml(pScene); xmlSerializer.ImportXml(pScene);
} }
} }

View File

@ -47,9 +47,9 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
/// @brief The 3MF-importer class.
class D3MFImporter : public BaseImporter { class D3MFImporter : public BaseImporter {
public: public:
// BaseImporter interface
D3MFImporter(); D3MFImporter();
~D3MFImporter(); ~D3MFImporter();
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const; bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const;

View File

@ -103,9 +103,9 @@ public:
std::string name = currentNode.name(); std::string name = currentNode.name();
if (name == "Relationship") { if (name == "Relationship") {
OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship()); OpcPackageRelationshipPtr relPtr(new OpcPackageRelationship());
relPtr->id = currentNode.attribute(XmlTag::RELS_ATTRIB_ID.c_str()).as_string(); relPtr->id = currentNode.attribute(XmlTag::RELS_ATTRIB_ID).as_string();
relPtr->type = currentNode.attribute(XmlTag::RELS_ATTRIB_TYPE.c_str()).as_string(); relPtr->type = currentNode.attribute(XmlTag::RELS_ATTRIB_TYPE).as_string();
relPtr->target = currentNode.attribute(XmlTag::RELS_ATTRIB_TARGET.c_str()).as_string(); relPtr->target = currentNode.attribute(XmlTag::RELS_ATTRIB_TARGET).as_string();
if (validateRels(relPtr)) { if (validateRels(relPtr)) {
m_relationShips.push_back(relPtr); m_relationShips.push_back(relPtr);
} }

View File

@ -205,7 +205,7 @@ void AMFImporter::ParseHelper_FixTruncatedFloatString(const char *pInStr, std::s
} }
static bool ParseHelper_Decode_Base64_IsBase64(const char pChar) { static bool ParseHelper_Decode_Base64_IsBase64(const char pChar) {
return (isalnum(pChar) || (pChar == '+') || (pChar == '/')); return (isalnum((unsigned char)pChar) || (pChar == '+') || (pChar == '/'));
} }
void AMFImporter::ParseHelper_Decode_Base64(const std::string &pInputBase64, std::vector<uint8_t> &pOutputData) const { void AMFImporter::ParseHelper_Decode_Base64(const std::string &pInputBase64, std::vector<uint8_t> &pOutputData) const {
@ -268,7 +268,8 @@ void AMFImporter::ParseFile(const std::string &pFile, IOSystem *pIOHandler) {
mXmlParser = new XmlParser(); mXmlParser = new XmlParser();
if (!mXmlParser->parse(file.get())) { if (!mXmlParser->parse(file.get())) {
delete mXmlParser; delete mXmlParser;
throw DeadlyImportError("Failed to create XML reader for file" + pFile + "."); mXmlParser = nullptr;
throw DeadlyImportError("Failed to create XML reader for file ", pFile, ".");
} }
// Start reading, search for root tag <amf> // Start reading, search for root tag <amf>
@ -517,10 +518,6 @@ bool AMFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool p
return false; return false;
} }
void AMFImporter::GetExtensionList(std::set<std::string> &pExtensionList) {
pExtensionList.insert("amf");
}
const aiImporterDesc *AMFImporter::GetInfo() const { const aiImporterDesc *AMFImporter::GetInfo() const {
return &Description; return &Description;
} }

View File

@ -277,7 +277,6 @@ public:
void ParseHelper_Node_Enter(AMFNodeElementBase *child); void ParseHelper_Node_Enter(AMFNodeElementBase *child);
void ParseHelper_Node_Exit(); void ParseHelper_Node_Exit();
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const; bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const;
void GetExtensionList(std::set<std::string> &pExtensionList);
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler); void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
const aiImporterDesc *GetInfo() const; const aiImporterDesc *GetInfo() const;
bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const; bool Find_NodeElement(const std::string &pID, const AMFNodeElementBase::EType pType, AMFNodeElementBase **pNodeElement) const;

View File

@ -428,10 +428,10 @@ void AMFImporter::Postprocess_BuildMeshSet(const AMFMesh &pNodeElement, const st
if (pBiggerThan != nullptr) { if (pBiggerThan != nullptr) {
bool found = false; bool found = false;
const size_t biggerThan = *pBiggerThan;
for (const SComplexFace &face : pFaceList) { for (const SComplexFace &face : pFaceList) {
for (size_t idx_vert = 0; idx_vert < face.Face.mNumIndices; idx_vert++) { for (size_t idx_vert = 0; idx_vert < face.Face.mNumIndices; idx_vert++) {
if (face.Face.mIndices[idx_vert] > *pBiggerThan) { if (face.Face.mIndices[idx_vert] > biggerThan) {
rv = face.Face.mIndices[idx_vert]; rv = face.Face.mIndices[idx_vert];
found = true; found = true;
break; break;

View File

@ -498,6 +498,12 @@ void Parser::ParseLV1MaterialListBlock() {
ParseLV2MaterialBlock(sMat); ParseLV2MaterialBlock(sMat);
continue; continue;
} }
if( iDepth == 1 ){
// CRUDE HACK: support missing brace after "Ascii Scene Exporter v2.51"
LogWarning("Missing closing brace in material list");
--filePtr;
return;
}
} }
AI_ASE_HANDLE_TOP_LEVEL_SECTION(); AI_ASE_HANDLE_TOP_LEVEL_SECTION();
} }

View File

@ -671,7 +671,7 @@ void AssbinImporter::ReadBinaryScene(IOStream *stream, aiScene *scene) {
void AssbinImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { void AssbinImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
IOStream *stream = pIOHandler->Open(pFile, "rb"); IOStream *stream = pIOHandler->Open(pFile, "rb");
if (nullptr == stream) { if (nullptr == stream) {
return; throw DeadlyImportError("ASSBIN: Could not open ", pFile);
} }
// signature // signature

View File

@ -359,7 +359,7 @@ void BVHLoader::ReadMotion(aiScene * /*pScene*/) {
std::string BVHLoader::GetNextToken() { std::string BVHLoader::GetNextToken() {
// skip any preceding whitespace // skip any preceding whitespace
while (mReader != mBuffer.end()) { while (mReader != mBuffer.end()) {
if (!isspace(*mReader)) if (!isspace((unsigned char)*mReader))
break; break;
// count lines // count lines
@ -372,7 +372,7 @@ std::string BVHLoader::GetNextToken() {
// collect all chars till the next whitespace. BVH is easy in respect to that. // collect all chars till the next whitespace. BVH is easy in respect to that.
std::string token; std::string token;
while (mReader != mBuffer.end()) { while (mReader != mBuffer.end()) {
if (isspace(*mReader)) if (isspace((unsigned char)*mReader))
break; break;
token.push_back(*mReader); token.push_back(*mReader);

View File

@ -132,12 +132,6 @@ bool BlenderImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bo
return false; return false;
} }
// ------------------------------------------------------------------------------------------------
// List all extensions handled by this loader
void BlenderImporter::GetExtensionList(std::set<std::string> &app) {
app.insert("blend");
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Loader registry entry // Loader registry entry
const aiImporterDesc *BlenderImporter::GetInfo() const { const aiImporterDesc *BlenderImporter::GetInfo() const {
@ -426,9 +420,9 @@ void BlenderImporter::ResolveImage(aiMaterial *out, const Material *mat, const M
--s; --s;
} }
curTex->achFormatHint[0] = s + 1 > e ? '\0' : (char)::tolower(s[1]); curTex->achFormatHint[0] = s + 1 > e ? '\0' : (char)::tolower((unsigned char)s[1]);
curTex->achFormatHint[1] = s + 2 > e ? '\0' : (char)::tolower(s[2]); curTex->achFormatHint[1] = s + 2 > e ? '\0' : (char)::tolower((unsigned char)s[2]);
curTex->achFormatHint[2] = s + 3 > e ? '\0' : (char)::tolower(s[3]); curTex->achFormatHint[2] = s + 3 > e ? '\0' : (char)::tolower((unsigned char)s[3]);
curTex->achFormatHint[3] = '\0'; curTex->achFormatHint[3] = '\0';
// tex->mHeight = 0; // tex->mHeight = 0;

View File

@ -110,7 +110,6 @@ public:
protected: protected:
const aiImporterDesc* GetInfo () const; const aiImporterDesc* GetInfo () const;
void GetExtensionList(std::set<std::string>& app);
void SetupProperties(const Importer* pImp); void SetupProperties(const Importer* pImp);
void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler); void InternReadFile( const std::string& pFile, aiScene* pScene, IOSystem* pIOHandler);
void ParseBlendFile(Blender::FileDatabase& out, std::shared_ptr<IOStream> stream); void ParseBlendFile(Blender::FileDatabase& out, std::shared_ptr<IOStream> stream);

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, 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,
@ -51,7 +51,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif #endif
#include "C4DImporter.h" #include "C4DImporter.h"
#include <assimp/TinyFormatter.h>
#include <memory> #include <memory>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/scene.h> #include <assimp/scene.h>
@ -65,7 +64,19 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "c4d_file.h" #include "c4d_file.h"
#include "default_alien_overloads.h" #include "default_alien_overloads.h"
using namespace melange; namespace {
aiString aiStringFrom(cineware::String const & cinestring) {
aiString result;
cinestring.GetCString(result.data, MAXLEN-1);
result.length = static_cast<ai_uint32>(cinestring.GetLength());
return result;
}
}
using namespace Assimp;
using namespace cineware;
// overload this function and fill in your own unique data // overload this function and fill in your own unique data
void GetWriterInfo(int &id, String &appname) { void GetWriterInfo(int &id, String &appname) {
@ -73,9 +84,6 @@ void GetWriterInfo(int &id, String &appname) {
appname = "Open Asset Import Library"; appname = "Open Asset Import Library";
} }
using namespace Assimp;
using namespace Assimp::Formatter;
namespace Assimp { namespace Assimp {
template<> const char* LogFunctions<C4DImporter>::Prefix() { template<> const char* LogFunctions<C4DImporter>::Prefix() {
static auto prefix = "C4D: "; static auto prefix = "C4D: ";
@ -97,17 +105,6 @@ static const aiImporterDesc desc = {
}; };
// ------------------------------------------------------------------------------------------------
C4DImporter::C4DImporter()
: BaseImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------
C4DImporter::~C4DImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const { bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
const std::string& extension = GetExtension(pFile); const std::string& extension = GetExtension(pFile);
@ -125,11 +122,6 @@ const aiImporterDesc* C4DImporter::GetInfo () const {
return &desc; return &desc;
} }
// ------------------------------------------------------------------------------------------------
void C4DImporter::SetupProperties(const Importer* /*pImp*/) {
// nothing to be done for the moment
}
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
@ -199,8 +191,8 @@ void C4DImporter::InternReadFile( const std::string& pFile, aiScene* pScene, IOS
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader) { bool C4DImporter::ReadShader(aiMaterial* out, BaseShader* shader) {
// based on Melange sample code (C4DImportExport.cpp) // based on Cineware sample code (C4DImportExport.cpp)
while(shader) { while(shader) {
if(shader->GetType() == Xlayer) { if(shader->GetType() == Xlayer) {
BaseContainer* container = shader->GetDataInstance(); BaseContainer* container = shader->GetDataInstance();
@ -242,9 +234,7 @@ bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader) {
lsl = lsl->GetNext(); lsl = lsl->GetNext();
} }
} else if ( shader->GetType() == Xbitmap ) { } else if ( shader->GetType() == Xbitmap ) {
aiString path; auto const path = aiStringFrom(shader->GetFileName().GetString());
shader->GetFileName().GetString().GetCString(path.data, MAXLEN-1);
path.length = ::strlen(path.data);
out->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0)); out->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0));
return true; return true;
} else { } else {
@ -257,18 +247,15 @@ bool C4DImporter::ReadShader(aiMaterial* out, melange::BaseShader* shader) {
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void C4DImporter::ReadMaterials(melange::BaseMaterial* mat) { void C4DImporter::ReadMaterials(BaseMaterial* mat) {
// based on Melange sample code // based on Cineware sample code
while (mat) { while (mat) {
const String& name = mat->GetName();
if (mat->GetType() == Mmaterial) { if (mat->GetType() == Mmaterial) {
aiMaterial* out = new aiMaterial(); aiMaterial* out = new aiMaterial();
material_mapping[mat] = static_cast<unsigned int>(materials.size()); material_mapping[mat] = static_cast<unsigned int>(materials.size());
materials.push_back(out); materials.push_back(out);
aiString ai_name; auto const ai_name = aiStringFrom(mat->GetName());
name.GetCString(ai_name.data, MAXLEN-1);
ai_name.length = ::strlen(ai_name.data);
out->AddProperty(&ai_name, AI_MATKEY_NAME); out->AddProperty(&ai_name, AI_MATKEY_NAME);
Material& m = dynamic_cast<Material&>(*mat); Material& m = dynamic_cast<Material&>(*mat);
@ -305,19 +292,15 @@ void C4DImporter::RecurseHierarchy(BaseObject* object, aiNode* parent) {
ai_assert(parent != nullptr ); ai_assert(parent != nullptr );
std::vector<aiNode*> nodes; std::vector<aiNode*> nodes;
// based on Melange sample code // based on Cineware sample code
while (object) { while (object) {
const String& name = object->GetName();
const LONG type = object->GetType(); const LONG type = object->GetType();
const Matrix& ml = object->GetMl(); const Matrix& ml = object->GetMl();
aiString string;
name.GetCString(string.data, MAXLEN-1);
string.length = ::strlen(string.data);
aiNode* const nd = new aiNode(); aiNode* const nd = new aiNode();
nd->mParent = parent; nd->mParent = parent;
nd->mName = string; nd->mName = aiStringFrom(object->GetName());
nd->mTransformation.a1 = ml.v1.x; nd->mTransformation.a1 = ml.v1.x;
nd->mTransformation.b1 = ml.v1.y; nd->mTransformation.b1 = ml.v1.y;
@ -370,7 +353,7 @@ aiMesh* C4DImporter::ReadMesh(BaseObject* object) {
ai_assert(object != nullptr); ai_assert(object != nullptr);
ai_assert( object->GetType() == Opolygon ); ai_assert( object->GetType() == Opolygon );
// based on Melange sample code // based on Cineware sample code
PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object); PolygonObject* const polyObject = dynamic_cast<PolygonObject*>(object);
ai_assert(polyObject != nullptr); ai_assert(polyObject != nullptr);
@ -618,4 +601,3 @@ unsigned int C4DImporter::ResolveMaterial(PolygonObject* obj) {
} }
#endif // ASSIMP_BUILD_NO_C4D_IMPORTER #endif // ASSIMP_BUILD_NO_C4D_IMPORTER

View File

@ -2,7 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2021, 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,
@ -56,8 +56,8 @@ struct aiMaterial;
struct aiImporterDesc; struct aiImporterDesc;
namespace melange { namespace cineware {
class BaseObject; // c4d_file.h class BaseObject;
class PolygonObject; class PolygonObject;
class BaseMaterial; class BaseMaterial;
class BaseShader; class BaseShader;
@ -71,43 +71,34 @@ namespace Assimp {
} }
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
/** Importer class to load Cinema4D files using the Melange library to be obtained from /** Importer class to load Cinema4D files using the Cineware library to be obtained from
* www.plugincafe.com * https://developers.maxon.net
* *
* Note that Melange is not free software. */ * Note that Cineware is not free software. */
// ------------------------------------------------------------------------------------------- // -------------------------------------------------------------------------------------------
class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter> { class C4DImporter : public BaseImporter, public LogFunctions<C4DImporter> {
public: public:
C4DImporter(); bool CanRead( const std::string& pFile, IOSystem*, bool checkSig) const override;
~C4DImporter();
bool CanRead( const std::string& pFile, IOSystem* pIOHandler,
bool checkSig) const;
protected: protected:
// -------------------- const aiImporterDesc* GetInfo () const override;
const aiImporterDesc* GetInfo () const;
// -------------------- void InternReadFile( const std::string& pFile, aiScene*, IOSystem* ) override;
void SetupProperties(const Importer* pImp);
// --------------------
void InternReadFile( const std::string& pFile, aiScene* pScene,
IOSystem* pIOHandler);
private: private:
void ReadMaterials(melange::BaseMaterial* mat); void ReadMaterials(cineware::BaseMaterial* mat);
void RecurseHierarchy(melange::BaseObject* object, aiNode* parent); void RecurseHierarchy(cineware::BaseObject* object, aiNode* parent);
aiMesh* ReadMesh(melange::BaseObject* object); aiMesh* ReadMesh(cineware::BaseObject* object);
unsigned int ResolveMaterial(melange::PolygonObject* obj); unsigned int ResolveMaterial(cineware::PolygonObject* obj);
bool ReadShader(aiMaterial* out, melange::BaseShader* shader); bool ReadShader(aiMaterial* out, cineware::BaseShader* shader);
std::vector<aiMesh*> meshes; std::vector<aiMesh*> meshes;
std::vector<aiMaterial*> materials; std::vector<aiMaterial*> materials;
typedef std::map<melange::BaseMaterial*, unsigned int> MaterialMap; typedef std::map<cineware::BaseMaterial*, unsigned int> MaterialMap;
MaterialMap material_mapping; MaterialMap material_mapping;
}; // !class C4DImporter }; // !class C4DImporter

View File

@ -137,7 +137,13 @@ void COBImporter::SetupProperties(const Importer * /*pImp*/) {
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) { void COBImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) {
COB::Scene scene; COB::Scene scene;
std::unique_ptr<StreamReaderLE> stream(new StreamReaderLE(pIOHandler->Open(pFile, "rb")));
auto file = pIOHandler->Open(pFile, "rb");
if (!file) {
ThrowException("Could not open " + pFile);
}
std::unique_ptr<StreamReaderLE> stream(new StreamReaderLE(file));
// check header // check header
char head[32]; char head[32];

View File

@ -75,7 +75,7 @@ static const aiImporterDesc desc = {
3, 3,
1, 1,
5, 5,
"dae zae" "dae xml zae"
}; };
static const float kMillisecondsFromSeconds = 1000.f; static const float kMillisecondsFromSeconds = 1000.f;

View File

@ -234,7 +234,7 @@ void ColladaParser::UriDecodePath(aiString &ss) {
#if defined(_MSC_VER) #if defined(_MSC_VER)
if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') { if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') {
#else #else
if (ss.data[0] == '/' && isalpha(ss.data[1]) && ss.data[2] == ':') { if (ss.data[0] == '/' && isalpha((unsigned char)ss.data[1]) && ss.data[2] == ':') {
#endif #endif
--ss.length; --ss.length;
::memmove(ss.data, ss.data + 1, ss.length); ::memmove(ss.data, ss.data + 1, ss.length);

View File

@ -1789,13 +1789,13 @@ void FBXExporter::WriteObjects ()
blendchannel_uid, blendshape_name + FBX::SEPARATOR + "SubDeformer", "BlendShapeChannel" blendchannel_uid, blendshape_name + FBX::SEPARATOR + "SubDeformer", "BlendShapeChannel"
); );
sdnode.AddChild("Version", int32_t(100)); sdnode.AddChild("Version", int32_t(100));
sdnode.AddChild("DeformPercent", int32_t(100)); sdnode.AddChild("DeformPercent", float_t(0.0));
FBX::Node p("Properties70"); FBX::Node p("Properties70");
p.AddP70numberA("DeformPercent", 100.); p.AddP70numberA("DeformPercent", 0.0);
sdnode.AddChild(p); sdnode.AddChild(p);
// TODO: Normally just one weight per channel, adding stub for later development // TODO: Normally just one weight per channel, adding stub for later development
std::vector<float>fFullWeights; std::vector<float>fFullWeights;
fFullWeights.push_back(0.); fFullWeights.push_back(100.);
sdnode.AddChild("FullWeights", fFullWeights); sdnode.AddChild("FullWeights", fFullWeights);
sdnode.Dump(outstream, binary, indent); sdnode.Dump(outstream, binary, indent);

View File

@ -82,7 +82,7 @@ Material::Material(uint64_t id, const Element& element, const Document& doc, con
// lower-case shading because Blender (for example) writes "Phong" // lower-case shading because Blender (for example) writes "Phong"
for (size_t i = 0; i < shading.length(); ++i) { for (size_t i = 0; i < shading.length(); ++i) {
shading[i] = static_cast<char>(tolower(shading[i])); shading[i] = static_cast<char>(tolower(static_cast<unsigned char>(shading[i])));
} }
std::string templateName; std::string templateName;
if(shading == "phong") { if(shading == "phong") {

View File

@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "AssetLib/HMP/HMPLoader.h" #include "AssetLib/HMP/HMPLoader.h"
#include "AssetLib/MD2/MD2FileData.h" #include "AssetLib/MD2/MD2FileData.h"
#include <assimp/StringUtils.h>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
@ -151,12 +152,7 @@ void HMPImporter::InternReadFile(const std::string &pFile,
InternReadFile_HMP7(); InternReadFile_HMP7();
} else { } else {
// Print the magic word to the logger // Print the magic word to the logger
char szBuffer[5]; std::string szBuffer = ai_str_toprintable((const char *)&iMagic, sizeof(iMagic));
szBuffer[0] = ((char *)&iMagic)[0];
szBuffer[1] = ((char *)&iMagic)[1];
szBuffer[2] = ((char *)&iMagic)[2];
szBuffer[3] = ((char *)&iMagic)[3];
szBuffer[4] = '\0';
delete[] mBuffer; delete[] mBuffer;
mBuffer = nullptr; mBuffer = nullptr;

View File

@ -115,7 +115,7 @@ static const aiImporterDesc desc = {
0, 0,
0, 0,
0, 0,
"ifc ifczip stp" "ifc ifczip step stp"
}; };
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------

View File

@ -859,13 +859,13 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == nullptr) { if (file.get() == nullptr) {
throw DeadlyImportError("Failed to open IRR file " + pFile); throw DeadlyImportError("Failed to open IRR file ", pFile);
} }
// Construct the irrXML parser // Construct the irrXML parser
XmlParser st; XmlParser st;
if (!st.parse( file.get() )) { if (!st.parse( file.get() )) {
return; throw DeadlyImportError("XML parse error while loading IRR file ", pFile);
} }
pugi::xml_node rootElement = st.getRootNode(); pugi::xml_node rootElement = st.getRootNode();

View File

@ -135,12 +135,12 @@ void IRRMeshImporter::InternReadFile(const std::string &pFile,
// Check whether we can read from the file // Check whether we can read from the file
if (file.get() == NULL) if (file.get() == NULL)
throw DeadlyImportError("Failed to open IRRMESH file " + pFile); throw DeadlyImportError("Failed to open IRRMESH file ", pFile);
// Construct the irrXML parser // Construct the irrXML parser
XmlParser parser; XmlParser parser;
if (!parser.parse( file.get() )) { if (!parser.parse( file.get() )) {
return; throw DeadlyImportError("XML parse error while loading IRRMESH file ", pFile);
} }
XmlNode root = parser.getRootNode(); XmlNode root = parser.getRootNode();

View File

@ -131,7 +131,7 @@ bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool c
*/ */
std::unique_ptr<IOStream> pStream(pIOHandler->Open(pFile, "rb")); std::unique_ptr<IOStream> pStream(pIOHandler->Open(pFile, "rb"));
unsigned char data[4]; unsigned char data[4];
if (4 != pStream->Read(data, 1, 4)) { if (!pStream || 4 != pStream->Read(data, 1, 4)) {
return false; return false;
} }
return !memcmp(data, "3DMO", 4) /* bin */ return !memcmp(data, "3DMO", 4) /* bin */

View File

@ -53,6 +53,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
#include <assimp/StringUtils.h>
#include <memory> #include <memory>
@ -148,46 +149,39 @@ void MD2Importer::ValidateHeader( )
if (m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_BE && if (m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_BE &&
m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_LE) m_pcHeader->magic != AI_MD2_MAGIC_NUMBER_LE)
{ {
char szBuffer[5]; throw DeadlyImportError("Invalid MD2 magic word: expected IDP2, found ",
szBuffer[0] = ((char*)&m_pcHeader->magic)[0]; ai_str_toprintable((char *)&m_pcHeader->magic, 4));
szBuffer[1] = ((char*)&m_pcHeader->magic)[1];
szBuffer[2] = ((char*)&m_pcHeader->magic)[2];
szBuffer[3] = ((char*)&m_pcHeader->magic)[3];
szBuffer[4] = '\0';
throw DeadlyImportError("Invalid MD2 magic word: should be IDP2, the "
"magic word found is " + std::string(szBuffer));
} }
// check file format version // check file format version
if (m_pcHeader->version != 8) if (m_pcHeader->version != 8)
ASSIMP_LOG_WARN( "Unsupported md2 file version. Continuing happily ..."); ASSIMP_LOG_WARN( "Unsupported MD2 file version. Continuing happily ...");
// check some values whether they are valid // check some values whether they are valid
if (0 == m_pcHeader->numFrames) if (0 == m_pcHeader->numFrames)
throw DeadlyImportError( "Invalid md2 file: NUM_FRAMES is 0"); throw DeadlyImportError( "Invalid MD2 file: NUM_FRAMES is 0");
if (m_pcHeader->offsetEnd > (uint32_t)fileSize) if (m_pcHeader->offsetEnd > (uint32_t)fileSize)
throw DeadlyImportError( "Invalid md2 file: File is too small"); throw DeadlyImportError( "Invalid MD2 file: File is too small");
if (m_pcHeader->numSkins > AI_MAX_ALLOC(MD2::Skin)) { if (m_pcHeader->numSkins > AI_MAX_ALLOC(MD2::Skin)) {
throw DeadlyImportError("Invalid MD2 header: too many skins, would overflow"); throw DeadlyImportError("Invalid MD2 header: Too many skins, would overflow");
} }
if (m_pcHeader->numVertices > AI_MAX_ALLOC(MD2::Vertex)) { if (m_pcHeader->numVertices > AI_MAX_ALLOC(MD2::Vertex)) {
throw DeadlyImportError("Invalid MD2 header: too many vertices, would overflow"); throw DeadlyImportError("Invalid MD2 header: Too many vertices, would overflow");
} }
if (m_pcHeader->numTexCoords > AI_MAX_ALLOC(MD2::TexCoord)) { if (m_pcHeader->numTexCoords > AI_MAX_ALLOC(MD2::TexCoord)) {
throw DeadlyImportError("Invalid MD2 header: too many texcoords, would overflow"); throw DeadlyImportError("Invalid MD2 header: Too many texcoords, would overflow");
} }
if (m_pcHeader->numTriangles > AI_MAX_ALLOC(MD2::Triangle)) { if (m_pcHeader->numTriangles > AI_MAX_ALLOC(MD2::Triangle)) {
throw DeadlyImportError("Invalid MD2 header: too many triangles, would overflow"); throw DeadlyImportError("Invalid MD2 header: Too many triangles, would overflow");
} }
if (m_pcHeader->numFrames > AI_MAX_ALLOC(MD2::Frame)) { if (m_pcHeader->numFrames > AI_MAX_ALLOC(MD2::Frame)) {
throw DeadlyImportError("Invalid MD2 header: too many frames, would overflow"); throw DeadlyImportError("Invalid MD2 header: Too many frames, would overflow");
} }
// -1 because Frame already contains one // -1 because Frame already contains one
@ -199,7 +193,7 @@ void MD2Importer::ValidateHeader( )
m_pcHeader->offsetFrames + m_pcHeader->numFrames * frameSize >= fileSize || m_pcHeader->offsetFrames + m_pcHeader->numFrames * frameSize >= fileSize ||
m_pcHeader->offsetEnd > fileSize) m_pcHeader->offsetEnd > fileSize)
{ {
throw DeadlyImportError("Invalid MD2 header: some offsets are outside the file"); throw DeadlyImportError("Invalid MD2 header: Some offsets are outside the file");
} }
if (m_pcHeader->numSkins > AI_MD2_MAX_SKINS) if (m_pcHeader->numSkins > AI_MD2_MAX_SKINS)
@ -210,7 +204,7 @@ void MD2Importer::ValidateHeader( )
ASSIMP_LOG_WARN("The model contains more vertices than Quake 2 supports"); ASSIMP_LOG_WARN("The model contains more vertices than Quake 2 supports");
if (m_pcHeader->numFrames <= configFrameID ) if (m_pcHeader->numFrames <= configFrameID )
throw DeadlyImportError("The requested frame is not existing the file"); throw DeadlyImportError("MD2: The requested frame (", configFrameID, ") does not exist in the file");
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -433,10 +427,6 @@ void MD2Importer::InternReadFile( const std::string& pFile,
aiVector3D& vNormal = pcMesh->mNormals[iCurrent]; aiVector3D& vNormal = pcMesh->mNormals[iCurrent];
LookupNormalIndex(pcVerts[iIndex].lightNormalIndex,vNormal); LookupNormalIndex(pcVerts[iIndex].lightNormalIndex,vNormal);
// flip z and y to become right-handed
std::swap((float&)vNormal.z,(float&)vNormal.y);
std::swap((float&)vec.z,(float&)vec.y);
if (m_pcHeader->numTexCoords) { if (m_pcHeader->numTexCoords) {
// validate texture coordinates // validate texture coordinates
iIndex = pcTriangles[i].textureIndices[c]; iIndex = pcTriangles[i].textureIndices[c];
@ -454,7 +444,15 @@ void MD2Importer::InternReadFile( const std::string& pFile,
} }
pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent; pScene->mMeshes[0]->mFaces[i].mIndices[c] = iCurrent;
} }
// flip the face order
std::swap( pScene->mMeshes[0]->mFaces[i].mIndices[0], pScene->mMeshes[0]->mFaces[i].mIndices[2] );
} }
// Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
pScene->mRootNode->mTransformation = aiMatrix4x4(
1.f, 0.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, -1.f, 0.f, 0.f,
0.f, 0.f, 0.f, 1.f);
} }
#endif // !! ASSIMP_BUILD_NO_MD2_IMPORTER #endif // !! ASSIMP_BUILD_NO_MD2_IMPORTER

View File

@ -702,7 +702,7 @@ void MD3Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
} }
filename = mFile.substr(s), path = mFile.substr(0, s); filename = mFile.substr(s), path = mFile.substr(0, s);
for (std::string::iterator it = filename.begin(); it != filename.end(); ++it) { for (std::string::iterator it = filename.begin(); it != filename.end(); ++it) {
*it = static_cast<char>(tolower(*it)); *it = static_cast<char>(tolower(static_cast<unsigned char>(*it)));
} }
// Load multi-part model file, if necessary // Load multi-part model file, if necessary

View File

@ -53,6 +53,7 @@ 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>
#include <assimp/Importer.hpp> #include <assimp/Importer.hpp>
#include <assimp/StringUtils.h>
#include <memory> #include <memory>
@ -143,16 +144,8 @@ void MDCImporter::ValidateHeader() {
if (pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_BE && if (pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_BE &&
pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_LE) { pcHeader->ulIdent != AI_MDC_MAGIC_NUMBER_LE) {
char szBuffer[5]; throw DeadlyImportError("Invalid MDC magic word: expected IDPC, found ",
szBuffer[0] = ((char *)&pcHeader->ulIdent)[0]; ai_str_toprintable((char *)&pcHeader->ulIdent, 4));
szBuffer[1] = ((char *)&pcHeader->ulIdent)[1];
szBuffer[2] = ((char *)&pcHeader->ulIdent)[2];
szBuffer[3] = ((char *)&pcHeader->ulIdent)[3];
szBuffer[4] = '\0';
throw DeadlyImportError("Invalid MDC magic word: should be IDPC, the "
"magic word found is " +
std::string(szBuffer));
} }
if (pcHeader->ulVersion != AI_MDC_VERSION) { if (pcHeader->ulVersion != AI_MDC_VERSION) {
@ -465,6 +458,13 @@ void MDCImporter::InternReadFile(
pcMat->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0)); pcMat->AddProperty(&path, AI_MATKEY_TEXTURE_DIFFUSE(0));
} }
} }
// Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
pScene->mRootNode->mTransformation = aiMatrix4x4(
1.f, 0.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
0.f, -1.f, 0.f, 0.f,
0.f, 0.f, 0.f, 1.f);
} }
#endif // !! ASSIMP_BUILD_NO_MDC_IMPORTER #endif // !! ASSIMP_BUILD_NO_MDC_IMPORTER

View File

@ -57,6 +57,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <iomanip> #include <iomanip>
#include <sstream> #include <sstream>
#include <map>
#ifdef MDL_HALFLIFE_LOG_WARN_HEADER #ifdef MDL_HALFLIFE_LOG_WARN_HEADER
#undef MDL_HALFLIFE_LOG_WARN_HEADER #undef MDL_HALFLIFE_LOG_WARN_HEADER
@ -868,7 +869,7 @@ void HL1MDLLoader::read_meshes() {
scene_mesh->mNormals[v] = bind_pose_normals[pTrivert->normindex]; scene_mesh->mNormals[v] = bind_pose_normals[pTrivert->normindex];
scene_mesh->mTextureCoords[0][v] = aiVector3D( scene_mesh->mTextureCoords[0][v] = aiVector3D(
pTrivert->s * texcoords_s_scale, pTrivert->s * texcoords_s_scale,
pTrivert->t * texcoords_t_scale, 0); pTrivert->t * -texcoords_t_scale, 0);
} }
// Add face and indices. // Add face and indices.
@ -879,9 +880,9 @@ void HL1MDLLoader::read_meshes() {
aiFace *face = &scene_mesh->mFaces[f]; aiFace *face = &scene_mesh->mFaces[f];
face->mNumIndices = 3; face->mNumIndices = 3;
face->mIndices = new unsigned int[3]; face->mIndices = new unsigned int[3];
face->mIndices[0] = mesh_faces[f].v0; face->mIndices[0] = mesh_faces[f].v2;
face->mIndices[1] = mesh_faces[f].v1; face->mIndices[1] = mesh_faces[f].v1;
face->mIndices[2] = mesh_faces[f].v2; face->mIndices[2] = mesh_faces[f].v0;
} }
// Add mesh bones. // Add mesh bones.

View File

@ -199,6 +199,7 @@ void MDLImporter::InternReadFile(const std::string &pFile,
const uint32_t iMagicWord = *((uint32_t *)mBuffer); const uint32_t iMagicWord = *((uint32_t *)mBuffer);
// Determine the file subtype and call the appropriate member function // Determine the file subtype and call the appropriate member function
bool is_half_life = false;
// Original Quake1 format // Original Quake1 format
if (AI_MDL_MAGIC_NUMBER_BE == iMagicWord || AI_MDL_MAGIC_NUMBER_LE == iMagicWord) { if (AI_MDL_MAGIC_NUMBER_BE == iMagicWord || AI_MDL_MAGIC_NUMBER_LE == iMagicWord) {
@ -240,6 +241,7 @@ void MDLImporter::InternReadFile(const std::string &pFile,
else if (AI_MDL_MAGIC_NUMBER_BE_HL2a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2a == iMagicWord || else if (AI_MDL_MAGIC_NUMBER_BE_HL2a == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2a == iMagicWord ||
AI_MDL_MAGIC_NUMBER_BE_HL2b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2b == iMagicWord) { AI_MDL_MAGIC_NUMBER_BE_HL2b == iMagicWord || AI_MDL_MAGIC_NUMBER_LE_HL2b == iMagicWord) {
iGSFileVersion = 0; iGSFileVersion = 0;
is_half_life = true;
HalfLife::HalfLifeMDLBaseHeader *pHeader = (HalfLife::HalfLifeMDLBaseHeader *)mBuffer; HalfLife::HalfLifeMDLBaseHeader *pHeader = (HalfLife::HalfLifeMDLBaseHeader *)mBuffer;
if (pHeader->version == AI_MDL_HL1_VERSION) { if (pHeader->version == AI_MDL_HL1_VERSION) {
@ -252,12 +254,22 @@ void MDLImporter::InternReadFile(const std::string &pFile,
} else { } else {
// print the magic word to the log file // print the magic word to the log file
throw DeadlyImportError("Unknown MDL subformat ", pFile, throw DeadlyImportError("Unknown MDL subformat ", pFile,
". Magic word (", std::string((char *)&iMagicWord, 4), ") is not known"); ". Magic word (", ai_str_toprintable((const char *)&iMagicWord, sizeof(iMagicWord)), ") is not known");
} }
// Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system if (is_half_life){
pScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f, // Now rotate the whole scene 90 degrees around the z and x axes to convert to internal coordinate system
0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f); pScene->mRootNode->mTransformation = aiMatrix4x4(
0.f, -1.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f,
-1.f, 0.f, 0.f, 0.f,
0.f, 0.f, 0.f, 1.f);
}
else {
// Now rotate the whole scene 90 degrees around the x axis to convert to internal coordinate system
pScene->mRootNode->mTransformation = aiMatrix4x4(1.f, 0.f, 0.f, 0.f,
0.f, 0.f, 1.f, 0.f, 0.f, -1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 1.f);
}
DeleteBufferAndCleanup(); DeleteBufferAndCleanup();
} catch (...) { } catch (...) {

View File

@ -478,8 +478,7 @@ namespace pmx
void PmxSoftBody::Read(std::istream * /*stream*/, PmxSetting * /*setting*/) void PmxSoftBody::Read(std::istream * /*stream*/, PmxSetting * /*setting*/)
{ {
std::cerr << "Not Implemented Exception" << std::endl; throw DeadlyImportError("MMD: Soft Body support is not implemented.");
throw DeadlyImportError("MMD: Not Implemented Exception");
} }
void PmxModel::Init() void PmxModel::Init()
@ -516,15 +515,13 @@ namespace pmx
char magic[4]; char magic[4];
stream->read((char*) magic, sizeof(char) * 4); stream->read((char*) magic, sizeof(char) * 4);
if (magic[0] != 0x50 || magic[1] != 0x4d || magic[2] != 0x58 || magic[3] != 0x20) if (magic[0] != 0x50 || magic[1] != 0x4d || magic[2] != 0x58 || magic[3] != 0x20)
{ {
std::cerr << "invalid magic number." << std::endl; throw DeadlyImportError("MMD: Invalid magic number.");
throw DeadlyImportError("MMD: invalid magic number.");
} }
stream->read((char*) &version, sizeof(float)); stream->read((char*) &version, sizeof(float));
if (version != 2.0f && version != 2.1f) if (version != 2.0f && version != 2.1f)
{ {
std::cerr << "this is not ver2.0 or ver2.1 but " << version << "." << std::endl; throw DeadlyImportError("MMD: Unsupported version (must be 2.0 or 2.1): ", ai_to_string(version));
throw DeadlyImportError("MMD: this is not ver2.0 or ver2.1 but ", ai_to_string(version));
} }
this->setting.Read(stream); this->setting.Read(stream);

View File

@ -215,7 +215,12 @@ void MS3DImporter :: CollectChildJoints(const std::vector<TempJoint>& joints, ai
void MS3DImporter::InternReadFile( const std::string& pFile, void MS3DImporter::InternReadFile( const std::string& pFile,
aiScene* pScene, IOSystem* pIOHandler) aiScene* pScene, IOSystem* pIOHandler)
{ {
StreamReaderLE stream(pIOHandler->Open(pFile,"rb"));
auto file = pIOHandler->Open(pFile, "rb");
if (!file)
throw DeadlyImportError("MS3D: Could not open ", pFile);
StreamReaderLE stream(file);
// CanRead() should have done this already // CanRead() should have done this already
char head[10]; char head[10];

View File

@ -116,7 +116,13 @@ void NDOImporter::SetupProperties(const Importer* /*pImp*/)
void NDOImporter::InternReadFile( const std::string& pFile, void NDOImporter::InternReadFile( const std::string& pFile,
aiScene* pScene, IOSystem* pIOHandler) aiScene* pScene, IOSystem* pIOHandler)
{ {
StreamReaderBE reader(pIOHandler->Open( pFile, "rb"));
auto file = pIOHandler->Open( pFile, "rb");
if (!file) {
throw DeadlyImportError("Nendo: Could not open ", pFile);
}
StreamReaderBE reader(file);
// first 9 bytes are nendo file format ("nendo 1.n") // first 9 bytes are nendo file format ("nendo 1.n")
const char* head = (const char*)reader.GetPtr(); const char* head = (const char*)reader.GetPtr();

View File

@ -45,6 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/DefaultIOSystem.h> #include <assimp/DefaultIOSystem.h>
#include <assimp/StringComparison.h> #include <assimp/StringComparison.h>
#include <assimp/StringUtils.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/ai_assert.h> #include <assimp/ai_assert.h>
@ -223,6 +224,18 @@ static void propId2StdString(Property *prop, std::string &name, std::string &key
} }
} }
//------------------------------------------------------------------------------------------------
static void logDDLParserMessage (LogSeverity severity, const std::string &rawmsg) {
std::string msg = ai_str_toprintable(rawmsg);
switch (severity) {
case ddl_debug_msg: ASSIMP_LOG_DEBUG(msg); break;
case ddl_info_msg: ASSIMP_LOG_INFO(msg); break;
case ddl_warn_msg: ASSIMP_LOG_WARN(msg); break;
case ddl_error_msg: ASSIMP_LOG_ERROR(msg); break;
default: ASSIMP_LOG_VERBOSE_DEBUG(msg); break;
}
}
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
OpenGEXImporter::VertexContainer::VertexContainer() : OpenGEXImporter::VertexContainer::VertexContainer() :
m_numColors(0), m_colors(nullptr), m_numUVComps(), m_textureCoords() { m_numColors(0), m_colors(nullptr), m_numUVComps(), m_textureCoords() {
@ -306,6 +319,7 @@ void OpenGEXImporter::InternReadFile(const std::string &filename, aiScene *pScen
pIOHandler->Close(file); pIOHandler->Close(file);
OpenDDLParser myParser; OpenDDLParser myParser;
myParser.setLogCallback(&logDDLParserMessage);
myParser.setBuffer(&buffer[0], buffer.size()); myParser.setBuffer(&buffer[0], buffer.size());
bool success(myParser.parse()); bool success(myParser.parse());
if (success) { if (success) {

View File

@ -172,7 +172,7 @@ void PLYImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
(headerCheck[1] != 'L' && headerCheck[1] != 'l') || (headerCheck[1] != 'L' && headerCheck[1] != 'l') ||
(headerCheck[2] != 'Y' && headerCheck[2] != 'y')) { (headerCheck[2] != 'Y' && headerCheck[2] != 'y')) {
streamedBuffer.close(); streamedBuffer.close();
throw DeadlyImportError("Invalid .ply file: Magic number \'ply\' is no there"); throw DeadlyImportError("Invalid .ply file: Incorrect magic number (expected 'ply' or 'PLY').");
} }
std::vector<char> mBuffer2; std::vector<char> mBuffer2;

View File

@ -75,7 +75,7 @@ static const aiImporterDesc desc = {
0, 0,
0, 0,
0, 0,
"pk3" "bsp pk3"
}; };
namespace Assimp { namespace Assimp {

View File

@ -47,6 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// internal headers // internal headers
#include "Q3DLoader.h" #include "Q3DLoader.h"
#include <assimp/StringUtils.h>
#include <assimp/StreamReader.h> #include <assimp/StreamReader.h>
#include <assimp/fast_atof.h> #include <assimp/fast_atof.h>
#include <assimp/importerdesc.h> #include <assimp/importerdesc.h>
@ -106,7 +107,12 @@ const aiImporterDesc *Q3DImporter::GetInfo() const {
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void Q3DImporter::InternReadFile(const std::string &pFile, void Q3DImporter::InternReadFile(const std::string &pFile,
aiScene *pScene, IOSystem *pIOHandler) { aiScene *pScene, IOSystem *pIOHandler) {
StreamReaderLE stream(pIOHandler->Open(pFile, "rb"));
auto file = pIOHandler->Open(pFile, "rb");
if (!file)
throw DeadlyImportError("Quick3D: Could not open ", pFile);
StreamReaderLE stream(file);
// The header is 22 bytes large // The header is 22 bytes large
if (stream.GetRemainingSize() < 22) if (stream.GetRemainingSize() < 22)
@ -115,7 +121,7 @@ void Q3DImporter::InternReadFile(const std::string &pFile,
// Check the file's signature // Check the file's signature
if (ASSIMP_strincmp((const char *)stream.GetPtr(), "quick3Do", 8) && if (ASSIMP_strincmp((const char *)stream.GetPtr(), "quick3Do", 8) &&
ASSIMP_strincmp((const char *)stream.GetPtr(), "quick3Ds", 8)) { ASSIMP_strincmp((const char *)stream.GetPtr(), "quick3Ds", 8)) {
throw DeadlyImportError("Not a Quick3D file. Signature string is: ", std::string((const char *)stream.GetPtr(), 8)); throw DeadlyImportError("Not a Quick3D file. Signature string is: ", ai_str_toprintable((const char *)stream.GetPtr(), 8));
} }
// Print the file format version // Print the file format version

View File

@ -68,6 +68,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h> #include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/IOSystem.hpp> #include <assimp/IOSystem.hpp>
#include <assimp/StringUtils.h>
#include <map> #include <map>
@ -166,14 +167,14 @@ static aiColor3D ReadColor(StreamReaderLE *stream) {
} }
static void UnknownChunk(StreamReaderLE * /*stream*/, const SIBChunk &chunk) { static void UnknownChunk(StreamReaderLE * /*stream*/, const SIBChunk &chunk) {
char temp[5] = { char temp[4] = {
static_cast<char>((chunk.Tag >> 24) & 0xff), static_cast<char>((chunk.Tag >> 24) & 0xff),
static_cast<char>((chunk.Tag >> 16) & 0xff), static_cast<char>((chunk.Tag >> 16) & 0xff),
static_cast<char>((chunk.Tag >> 8) & 0xff), static_cast<char>((chunk.Tag >> 8) & 0xff),
static_cast<char>(chunk.Tag & 0xff), '\0' static_cast<char>(chunk.Tag & 0xff)
}; };
ASSIMP_LOG_WARN((Formatter::format(), "SIB: Skipping unknown '", temp, "' chunk.")); ASSIMP_LOG_WARN((Formatter::format(), "SIB: Skipping unknown '", ai_str_toprintable(temp, 4), "' chunk."));
} }
// Reads a UTF-16LE string and returns it at UTF-8. // Reads a UTF-16LE string and returns it at UTF-8.
@ -804,7 +805,12 @@ static void ReadScene(SIB *sib, StreamReaderLE *stream) {
// Imports the given file into the given scene structure. // Imports the given file into the given scene structure.
void SIBImporter::InternReadFile(const std::string &pFile, void SIBImporter::InternReadFile(const std::string &pFile,
aiScene *pScene, IOSystem *pIOHandler) { aiScene *pScene, IOSystem *pIOHandler) {
StreamReaderLE stream(pIOHandler->Open(pFile, "rb"));
auto file = pIOHandler->Open(pFile, "rb");
if (!file)
throw DeadlyImportError("SIB: Could not open ", pFile);
StreamReaderLE stream(file);
// We should have at least one chunk // We should have at least one chunk
if (stream.GetRemainingSize() < 16) if (stream.GetRemainingSize() < 16)

View File

@ -667,8 +667,8 @@ void XFileImporter::ConvertMaterials( aiScene* pScene, std::vector<XFile::Materi
// 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 ) {
if ( isalpha( sz[ c ] ) ) { if ( isalpha( (unsigned char) sz[ c ] ) ) {
sz[ c ] = (char) tolower( sz[ c ] ); sz[ c ] = (char) tolower( (unsigned char) sz[ c ] );
} }
} }

View File

@ -1245,13 +1245,13 @@ unsigned int XFileParser::ReadInt() {
} }
// at least one digit expected // at least one digit expected
if (!isdigit(*mP)) if (!isdigit((unsigned char)*mP))
ThrowException("Number expected."); ThrowException("Number expected.");
// read digits // read digits
unsigned int number = 0; unsigned int number = 0;
while (mP < mEnd) { while (mP < mEnd) {
if (!isdigit(*mP)) if (!isdigit((unsigned char)*mP))
break; break;
number = number * 10 + (*mP - 48); number = number * 10 + (*mP - 48);
mP++; mP++;

View File

@ -167,10 +167,6 @@ bool X3DImporter::CanRead( const std::string &pFile, IOSystem * /*pIOHandler*/,
return false; return false;
} }
void X3DImporter::GetExtensionList( std::set<std::string> &extensionList ) {
extensionList.insert("x3d");
}
void X3DImporter::InternReadFile( const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler ) { void X3DImporter::InternReadFile( const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler ) {
std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb")); std::shared_ptr<IOStream> stream(pIOHandler->Open(pFile, "rb"));
if (!stream) { if (!stream) {

View File

@ -307,7 +307,6 @@ public:
/// \param [in] pIOHandler - pointer to IO helper object. /// \param [in] pIOHandler - pointer to IO helper object.
void ParseFile(const std::string &pFile, IOSystem *pIOHandler); void ParseFile(const std::string &pFile, IOSystem *pIOHandler);
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const; bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const;
void GetExtensionList(std::set<std::string> &pExtensionList);
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler); void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler);
const aiImporterDesc *GetInfo() const; const aiImporterDesc *GetInfo() const;
void Clear(); void Clear();

View File

@ -200,7 +200,7 @@ void XGLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// parse the XML file // parse the XML file
mXmlParser = new XmlParser; mXmlParser = new XmlParser;
if (!mXmlParser->parse(stream.get())) { if (!mXmlParser->parse(stream.get())) {
return; throw DeadlyImportError("XML parse error while loading XGL file ", pFile);
} }
TempScope scope; TempScope scope;

View File

@ -47,7 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp { namespace Assimp {
CIOStreamWrapper::~CIOStreamWrapper(void) { CIOStreamWrapper::~CIOStreamWrapper() {
/* Various places depend on this destructor to close the file */ /* Various places depend on this destructor to close the file */
if (mFile) { if (mFile) {
mIO->mFileSystem->CloseProc(mIO->mFileSystem, mFile); mIO->mFileSystem->CloseProc(mIO->mFileSystem, mFile);
@ -78,7 +78,7 @@ aiReturn CIOStreamWrapper::Seek(size_t pOffset,
} }
// ................................................................... // ...................................................................
size_t CIOStreamWrapper::Tell(void) const { size_t CIOStreamWrapper::Tell() const {
return mFile->TellProc(mFile); return mFile->TellProc(mFile);
} }

View File

@ -65,20 +65,6 @@ using namespace Assimp;
// Constructor to be privately used by Importer // Constructor to be privately used by Importer
BaseImporter::BaseImporter() AI_NO_EXCEPT BaseImporter::BaseImporter() AI_NO_EXCEPT
: m_progress() { : m_progress() {
/**
* Assimp Importer
* unit conversions available
* if you need another measurment unit add it below.
* it's currently defined in assimp that we prefer meters.
*
* NOTE: Initialised here rather than in the header file
* to workaround a VS2013 bug with brace initialisers
* */
importerUnits[ImporterUnits::M] = 1.0;
importerUnits[ImporterUnits::CM] = 0.01;
importerUnits[ImporterUnits::MM] = 0.001;
importerUnits[ImporterUnits::INCHES] = 0.0254;
importerUnits[ImporterUnits::FEET] = 0.3048;
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -97,7 +83,7 @@ void BaseImporter::UpdateImporterScale(Importer *pImp) {
// Set active scaling // Set active scaling
pImp->SetPropertyFloat(AI_CONFIG_APP_SCALE_KEY, static_cast<float>(activeScale)); pImp->SetPropertyFloat(AI_CONFIG_APP_SCALE_KEY, static_cast<float>(activeScale));
ASSIMP_LOG_DEBUG_F("UpdateImporterScale scale set: %f", activeScale); ASSIMP_LOG_DEBUG_F("UpdateImporterScale scale set: ", activeScale);
} }
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
@ -193,7 +179,7 @@ void BaseImporter::GetExtensionList(std::set<std::string> &extensions) {
} }
for (size_t i = 0; i < read; ++i) { for (size_t i = 0; i < read; ++i) {
buffer[i] = static_cast<char>(::tolower(buffer[i])); buffer[i] = static_cast<char>(::tolower((unsigned char)buffer[i]));
} }
// It is not a proper handling of unicode files here ... // It is not a proper handling of unicode files here ...
@ -214,7 +200,7 @@ void BaseImporter::GetExtensionList(std::set<std::string> &extensions) {
token.clear(); token.clear();
const char *ptr(tokens[i]); const char *ptr(tokens[i]);
for (size_t tokIdx = 0; tokIdx < len; ++tokIdx) { for (size_t tokIdx = 0; tokIdx < len; ++tokIdx) {
token.push_back(static_cast<char>(tolower(*ptr))); token.push_back(static_cast<char>(tolower(static_cast<unsigned char>(*ptr))));
++ptr; ++ptr;
} }
const char *r = strstr(buffer, token.c_str()); const char *r = strstr(buffer, token.c_str());
@ -223,7 +209,7 @@ void BaseImporter::GetExtensionList(std::set<std::string> &extensions) {
} }
// We need to make sure that we didn't accidentially identify the end of another token as our token, // We need to make sure that we didn't accidentially identify the end of another token as our token,
// e.g. in a previous version the "gltf " present in some gltf files was detected as "f " // e.g. in a previous version the "gltf " present in some gltf files was detected as "f "
if (noAlphaBeforeTokens && (r != buffer && isalpha(r[-1]))) { if (noAlphaBeforeTokens && (r != buffer && isalpha(static_cast<unsigned char>(r[-1])))) {
continue; continue;
} }
// We got a match, either we don't care where it is, or it happens to // We got a match, either we don't care where it is, or it happens to

View File

@ -48,6 +48,7 @@ corresponding preprocessor flag to selectively disable formats.
#include <assimp/BaseImporter.h> #include <assimp/BaseImporter.h>
#include <vector> #include <vector>
#include <cstdlib>
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
// Importers // Importers
@ -204,7 +205,17 @@ corresponding preprocessor flag to selectively disable formats.
namespace Assimp { namespace Assimp {
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void GetImporterInstanceList(std::vector<BaseImporter *> &out) { void GetImporterInstanceList(std::vector<BaseImporter *> &out) {
// Some importers may be unimplemented or otherwise unsuitable for general use
// in their current state. Devs can set ASSIMP_ENABLE_DEV_IMPORTERS in their
// local environment to enable them, otherwise they're left out of the registry.
const char *envStr = std::getenv("ASSIMP_ENABLE_DEV_IMPORTERS");
bool devImportersEnabled = envStr && strcmp(envStr, "0");
// Ensure no unused var warnings if all uses are #ifndef'd away below:
(void)devImportersEnabled;
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
// Add an instance of each worker class here // Add an instance of each worker class here
// (register_new_importers_here) // (register_new_importers_here)
@ -354,7 +365,9 @@ void GetImporterInstanceList(std::vector<BaseImporter *> &out) {
out.push_back(new D3MFImporter()); out.push_back(new D3MFImporter());
#endif #endif
#ifndef ASSIMP_BUILD_NO_X3D_IMPORTER #ifndef ASSIMP_BUILD_NO_X3D_IMPORTER
out.push_back(new X3DImporter()); if (devImportersEnabled) { // https://github.com/assimp/assimp/issues/3647
out.push_back(new X3DImporter());
}
#endif #endif
#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER #ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
out.push_back(new MMDImporter()); out.push_back(new MMDImporter());

View File

@ -45,7 +45,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// possible as new fields are added to assimp structures. // possible as new fields are added to assimp structures.
// ---------------------------------------------------------------------------- // ----------------------------------------------------------------------------
/** /**
* @file Implements Assimp::SceneCombiner. This is a smart utility * @file Implements Assimp::SceneCombiner. This is a smart utility
* class that combines multiple scenes, meshes, ... into one. Currently * class that combines multiple scenes, meshes, ... into one. Currently
* these utilities are used by the IRR and LWS loaders and the * these utilities are used by the IRR and LWS loaders and the
@ -359,7 +359,7 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector<At
// generate the output texture list + an offset table for all texture indices // generate the output texture list + an offset table for all texture indices
if (dest->mNumTextures) { if (dest->mNumTextures) {
aiTexture **pip = dest->mTextures = new aiTexture *[dest->mNumMaterials]; aiTexture **pip = dest->mTextures = new aiTexture *[dest->mNumTextures];
cnt = 0; cnt = 0;
for (unsigned int n = 0; n < src.size(); ++n) { for (unsigned int n = 0; n < src.size(); ++n) {
SceneHelper *cur = &src[n]; SceneHelper *cur = &src[n];
@ -638,6 +638,8 @@ void SceneCombiner::MergeScenes(aiScene **_dest, aiScene *master, std::vector<At
deleteMe->mMaterials = nullptr; deleteMe->mMaterials = nullptr;
delete[] deleteMe->mAnimations; delete[] deleteMe->mAnimations;
deleteMe->mAnimations = nullptr; deleteMe->mAnimations = nullptr;
delete[] deleteMe->mTextures;
deleteMe->mTextures = nullptr;
deleteMe->mRootNode = nullptr; deleteMe->mRootNode = nullptr;

View File

@ -70,6 +70,7 @@ GenFaceNormalsProcess::~GenFaceNormalsProcess() {
// 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 GenFaceNormalsProcess::IsActive(unsigned int pFlags) const { bool GenFaceNormalsProcess::IsActive(unsigned int pFlags) const {
force_ = (pFlags & aiProcess_ForceGenNormals) != 0; force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
flippedWindingOrder_ = (pFlags & aiProcess_FlipWindingOrder) != 0;
return (pFlags & aiProcess_GenNormals) != 0; return (pFlags & aiProcess_GenNormals) != 0;
} }
@ -134,6 +135,8 @@ bool GenFaceNormalsProcess::GenMeshFaceNormals(aiMesh *pMesh) {
const aiVector3D *pV1 = &pMesh->mVertices[face.mIndices[0]]; const aiVector3D *pV1 = &pMesh->mVertices[face.mIndices[0]];
const aiVector3D *pV2 = &pMesh->mVertices[face.mIndices[1]]; const aiVector3D *pV2 = &pMesh->mVertices[face.mIndices[1]];
const aiVector3D *pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices - 1]]; const aiVector3D *pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices - 1]];
if (flippedWindingOrder_)
std::swap( pV2, pV3 );
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe(); const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
for (unsigned int i = 0; i < face.mNumIndices; ++i) { for (unsigned int i = 0; i < face.mNumIndices; ++i) {

View File

@ -80,6 +80,7 @@ public:
private: private:
bool GenMeshFaceNormals(aiMesh* pcMesh); bool GenMeshFaceNormals(aiMesh* pcMesh);
mutable bool force_ = false; mutable bool force_ = false;
mutable bool flippedWindingOrder_ = false;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -70,6 +70,7 @@ GenVertexNormalsProcess::~GenVertexNormalsProcess() {
// 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 GenVertexNormalsProcess::IsActive(unsigned int pFlags) const { bool GenVertexNormalsProcess::IsActive(unsigned int pFlags) const {
force_ = (pFlags & aiProcess_ForceGenNormals) != 0; force_ = (pFlags & aiProcess_ForceGenNormals) != 0;
flippedWindingOrder_ = (pFlags & aiProcess_FlipWindingOrder) != 0;
return (pFlags & aiProcess_GenSmoothNormals) != 0; return (pFlags & aiProcess_GenSmoothNormals) != 0;
} }
@ -142,6 +143,8 @@ bool GenVertexNormalsProcess::GenMeshVertexNormals(aiMesh *pMesh, unsigned int m
const aiVector3D *pV1 = &pMesh->mVertices[face.mIndices[0]]; const aiVector3D *pV1 = &pMesh->mVertices[face.mIndices[0]];
const aiVector3D *pV2 = &pMesh->mVertices[face.mIndices[1]]; const aiVector3D *pV2 = &pMesh->mVertices[face.mIndices[1]];
const aiVector3D *pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices - 1]]; const aiVector3D *pV3 = &pMesh->mVertices[face.mIndices[face.mNumIndices - 1]];
if (flippedWindingOrder_)
std::swap( pV2, pV3 );
const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe(); const aiVector3D vNor = ((*pV2 - *pV1) ^ (*pV3 - *pV1)).NormalizeSafe();
for (unsigned int i = 0; i < face.mNumIndices; ++i) { for (unsigned int i = 0; i < face.mNumIndices; ++i) {

View File

@ -104,6 +104,7 @@ private:
/** Configuration option: maximum smoothing angle, in radians*/ /** Configuration option: maximum smoothing angle, in radians*/
ai_real configMaxAngle; ai_real configMaxAngle;
mutable bool force_ = false; mutable bool force_ = false;
mutable bool flippedWindingOrder_ = false;
}; };
} // end of namespace Assimp } // end of namespace Assimp

View File

@ -429,7 +429,7 @@ void PretransformVertices::Execute(aiScene *pScene) {
const unsigned int iOldNodes = CountNodes(pScene->mRootNode); const unsigned int iOldNodes = CountNodes(pScene->mRootNode);
if (configTransform) { if (configTransform) {
pScene->mRootNode->mTransformation = configTransformation; pScene->mRootNode->mTransformation = configTransformation * pScene->mRootNode->mTransformation;
} }
// first compute absolute transformation matrices for all nodes // first compute absolute transformation matrices for all nodes

View File

@ -252,7 +252,7 @@ DecoderBuffer ParseLineIntoDecoderBuffer(DecoderBuffer *buffer) {
std::string ToLower(const std::string &str) { std::string ToLower(const std::string &str) {
std::string out; std::string out;
std::transform(str.begin(), str.end(), std::back_inserter(out), tolower); std::transform(str.begin(), str.end(), std::back_inserter(out), [](unsigned char c){return tolower(c);});
return out; return out;
} }

View File

@ -268,14 +268,14 @@ std::vector<std::string> PlyReader::SplitWords(const std::string &line) {
while ((end = line.find_first_of(" \t\n\v\f\r", start)) != while ((end = line.find_first_of(" \t\n\v\f\r", start)) !=
std::string::npos) { std::string::npos) {
const std::string word(line.substr(start, end - start)); const std::string word(line.substr(start, end - start));
if (!std::all_of(word.begin(), word.end(), isspace)) { if (!std::all_of(word.begin(), word.end(), [](unsigned char c){return isspace(c);})) {
output.push_back(word); output.push_back(word);
} }
start = end + 1; start = end + 1;
} }
const std::string last_word(line.substr(start)); const std::string last_word(line.substr(start));
if (!std::all_of(last_word.begin(), last_word.end(), isspace)) { if (!std::all_of(last_word.begin(), last_word.end(), [](unsigned char c){return isspace(c);})) {
output.push_back(last_word); output.push_back(last_word);
} }
return output; return output;

View File

@ -644,7 +644,7 @@ class ParameterizedTestCaseInfo : public ParameterizedTestCaseInfoBase {
// Check for invalid characters // Check for invalid characters
for (std::string::size_type index = 0; index < name.size(); ++index) { for (std::string::size_type index = 0; index < name.size(); ++index) {
if (!isalnum(name[index]) && name[index] != '_') if (!IsAlNum(name[index]) && name[index] != '_')
return false; return false;
} }

View File

@ -72,13 +72,15 @@ const char *getTypeToken(Value::ValueType type) {
} }
static void logInvalidTokenError(char *in, const std::string &exp, OpenDDLParser::logCallback callback) { static void logInvalidTokenError(char *in, const std::string &exp, OpenDDLParser::logCallback callback) {
std::stringstream stream; if (callback) {
stream << "Invalid token \"" << *in << "\"" std::string full(in);
<< " expected \"" << exp << "\"" << std::endl; std::string part(full.substr(0, 50));
std::string full(in); std::stringstream stream;
std::string part(full.substr(0, 50)); stream << "Invalid token \"" << *in << "\" "
stream << part; << "(expected \"" << exp << "\") "
callback(ddl_error_msg, stream.str()); << "in: \"" << part << "\"";
callback(ddl_error_msg, stream.str());
}
} }
static bool isIntegerType(Value::ValueType integerType) { static bool isIntegerType(Value::ValueType integerType) {
@ -111,26 +113,8 @@ static DDLNode *createDDLNode(Text *id, OpenDDLParser *parser) {
return node; return node;
} }
static void logMessage(LogSeverity severity, const std::string &msg) {
std::string log;
if (ddl_debug_msg == severity) {
log += "Debug:";
} else if (ddl_info_msg == severity) {
log += "Info :";
} else if (ddl_warn_msg == severity) {
log += "Warn :";
} else if (ddl_error_msg == severity) {
log += "Error:";
} else {
log += "None :";
}
log += msg;
std::cout << log;
}
OpenDDLParser::OpenDDLParser() : OpenDDLParser::OpenDDLParser() :
m_logCallback(logMessage), m_logCallback(nullptr),
m_buffer(), m_buffer(),
m_stack(), m_stack(),
m_context(nullptr) { m_context(nullptr) {
@ -138,7 +122,7 @@ OpenDDLParser::OpenDDLParser() :
} }
OpenDDLParser::OpenDDLParser(const char *buffer, size_t len) : OpenDDLParser::OpenDDLParser(const char *buffer, size_t len) :
m_logCallback(&logMessage), m_buffer(), m_context(nullptr) { m_logCallback(nullptr), m_buffer(), m_context(nullptr) {
if (0 != len) { if (0 != len) {
setBuffer(buffer, len); setBuffer(buffer, len);
} }
@ -149,13 +133,8 @@ OpenDDLParser::~OpenDDLParser() {
} }
void OpenDDLParser::setLogCallback(logCallback callback) { void OpenDDLParser::setLogCallback(logCallback callback) {
if (nullptr != callback) { // install user-specific log callback; null = no log callback
// install user-specific log callback m_logCallback = callback;
m_logCallback = callback;
} else {
// install default log callback
m_logCallback = &logMessage;
}
} }
OpenDDLParser::logCallback OpenDDLParser::getLogCallback() const { OpenDDLParser::logCallback OpenDDLParser::getLogCallback() const {

View File

@ -44,7 +44,7 @@
#ifdef _MSC_VER #ifdef _MSC_VER
#include <io.h> #include <io.h>
#pragma warning(disable : 4706) #pragma warning(disable : 4706 4244 4028)
#define ftruncate(fd, sz) (-(_chsize_s((fd), (sz)) != 0)) #define ftruncate(fd, sz) (-(_chsize_s((fd), (sz)) != 0))
#define fileno _fileno #define fileno _fileno

View File

@ -81,6 +81,7 @@ __Exporters__:
- JSON (for WebGl, via https://github.com/acgessler/assimp2json) - JSON (for WebGl, via https://github.com/acgessler/assimp2json)
- ASSBIN - ASSBIN
- STEP - STEP
- [PBRTv4](https://github.com/mmp/pbrt-v4)
- glTF 1.0 (partial) - glTF 1.0 (partial)
- glTF 2.0 (partial) - glTF 2.0 (partial)
- 3MF ( experimental ) - 3MF ( experimental )

View File

@ -51,10 +51,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "Exceptional.h" #include "Exceptional.h"
#include <assimp/ai_assert.h>
#include <assimp/types.h> #include <assimp/types.h>
#include <assimp/ProgressHandler.hpp> #include <assimp/ProgressHandler.hpp>
#include <map>
#include <set> #include <set>
#include <vector> #include <vector>
#include <memory> #include <memory>
@ -179,42 +177,10 @@ public:
/** /**
* Will be called only by scale process when scaling is requested. * Will be called only by scale process when scaling is requested.
*/ */
virtual void SetFileScale(double scale) { void SetFileScale(double scale) {
fileScale = scale; fileScale = scale;
} }
virtual double GetFileScale() const {
return fileScale;
}
enum ImporterUnits {
M,
MM,
CM,
INCHES,
FEET
};
/**
* Assimp Importer
* unit conversions available
* NOTE: Valid options are initialised in the
* constructor in the implementation file to
* work around a VS2013 compiler bug if support
* for that compiler is dropped in the future
* initialisation can be moved back here
* */
std::map<ImporterUnits, double> importerUnits;
virtual void SetApplicationUnits(const ImporterUnits &unit) {
importerScale = importerUnits[unit];
applicationUnits = unit;
}
virtual const ImporterUnits &GetApplicationUnits() {
return applicationUnits;
}
// ------------------------------------------------------------------- // -------------------------------------------------------------------
/** Called by #Importer::GetExtensionList for each loaded importer. /** Called by #Importer::GetExtensionList for each loaded importer.
* Take the extension list contained in the structure returned by * Take the extension list contained in the structure returned by
@ -223,7 +189,6 @@ public:
void GetExtensionList(std::set<std::string> &extensions); void GetExtensionList(std::set<std::string> &extensions);
protected: protected:
ImporterUnits applicationUnits = ImporterUnits::M;
double importerScale = 1.0; double importerScale = 1.0;
double fileScale = 1.0; double fileScale = 1.0;
@ -420,7 +385,7 @@ public: // static utilities
private: private:
/* Pushes state into importer for the importer scale */ /* Pushes state into importer for the importer scale */
virtual void UpdateImporterScale(Importer *pImp); void UpdateImporterScale(Importer *pImp);
protected: protected:
/// Error description in case there was one. /// Error description in case there was one.

View File

@ -262,7 +262,7 @@ AI_FORCE_INLINE unsigned int tokenize(const string_type &str, std::vector<string
inline std::string ai_stdStrToLower(const std::string &str) { inline std::string ai_stdStrToLower(const std::string &str) {
std::string out(str); std::string out(str);
for (size_t i = 0; i < str.size(); ++i) { for (size_t i = 0; i < str.size(); ++i) {
out[i] = (char) tolower(out[i]); out[i] = (char) tolower((unsigned char)out[i]);
} }
return out; return out;
} }

View File

@ -146,8 +146,8 @@ inline int ASSIMP_stricmp(const char *s1, const char *s2) {
#else #else
char c1, c2; char c1, c2;
do { do {
c1 = tolower(*s1++); c1 = tolower((unsigned char)*(s1++));
c2 = tolower(*s2++); c2 = tolower((unsigned char)*(s2++));
} while (c1 && (c1 == c2)); } while (c1 && (c1 == c2));
return c1 - c2; return c1 - c2;
#endif #endif
@ -197,8 +197,8 @@ inline int ASSIMP_strincmp(const char *s1, const char *s2, unsigned int n) {
unsigned int p = 0; unsigned int p = 0;
do { do {
if (p++ >= n) return 0; if (p++ >= n) return 0;
c1 = tolower(*s1++); c1 = tolower((unsigned char)*(s1++));
c2 = tolower(*s2++); c2 = tolower((unsigned char)*(s2++));
} while (c1 && (c1 == c2)); } while (c1 && (c1 == c2));
return c1 - c2; return c1 - c2;

View File

@ -4,7 +4,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2021, assimp team Copyright (c) 2006-2021, 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,
@ -55,6 +54,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cstdlib> #include <cstdlib>
#include <locale> #include <locale>
#include <sstream> #include <sstream>
#include <iomanip>
#ifdef _MSC_VER #ifdef _MSC_VER
#define AI_SIZEFMT "%Iu" #define AI_SIZEFMT "%Iu"
@ -157,7 +157,7 @@ AI_FORCE_INLINE std::string ai_decimal_to_hexa(T toConvert) {
ss >> result; ss >> result;
for (size_t i = 0; i < result.size(); ++i) { for (size_t i = 0; i < result.size(); ++i) {
result[i] = (char)toupper(result[i]); result[i] = (char)toupper((unsigned char)result[i]);
} }
return result; return result;
@ -177,7 +177,7 @@ AI_FORCE_INLINE std::string ai_rgba2hex(int r, int g, int b, int a, bool with_he
if (with_head) { if (with_head) {
ss << "#"; ss << "#";
} }
ss << std::hex << (r << 24 | g << 16 | b << 8 | a); ss << std::hex << std::setfill('0') << std::setw(8) << (r << 24 | g << 16 | b << 8 | a);
return ss.str(); return ss.str();
} }
@ -249,4 +249,31 @@ AI_FORCE_INLINE std::string ai_str_toupper(const std::string &in) {
return out; return out;
} }
#endif // ---------------------------------------------------------------------------------
/// @brief Make a string printable by replacing all non-printable characters with
/// the specified placeholder character.
/// @param in The incoming string.
/// @param placeholder Placeholder character, default is a question mark.
/// @return The string, with all non-printable characters replaced.
AI_FORCE_INLINE std::string ai_str_toprintable(const std::string &in, char placeholder = '?') {
std::string out(in);
std::transform(out.begin(), out.end(), out.begin(), [placeholder] (unsigned char c) {
return isprint(c) ? (char)c : placeholder;
});
return out;
}
// ---------------------------------------------------------------------------------
/// @brief Make a string printable by replacing all non-printable characters with
/// the specified placeholder character.
/// @param in The incoming string.
/// @param len The length of the incoming string.
/// @param placeholder Placeholder character, default is a question mark.
/// @return The string, with all non-printable characters replaced. Will return an
/// empty string if in is null or len is <= 0.
AI_FORCE_INLINE std::string ai_str_toprintable(const char *in, int len, char placeholder = '?') {
return (in && len > 0) ? ai_str_toprintable(std::string(in, len), placeholder) : std::string();
}
#endif // INCLUDED_AI_STRINGUTILS_H

View File

@ -43,8 +43,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#define INCLUDED_AI_IRRXML_WRAPPER #define INCLUDED_AI_IRRXML_WRAPPER
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/ai_assert.h>
#include "BaseImporter.h" #include "BaseImporter.h"
#include "IOStream.hpp" #include "IOStream.hpp"
#include <pugixml.hpp> #include <pugixml.hpp>
#include <vector> #include <vector>
@ -136,7 +139,9 @@ public:
if (parse_result.status == pugi::status_ok) { if (parse_result.status == pugi::status_ok) {
return true; return true;
} else { } else {
ASSIMP_LOG_DEBUG("Error while parse xml."); std::ostringstream oss;
oss << "Error while parsing XML: " << parse_result.description() << " @ " << parse_result.offset;
ASSIMP_LOG_DEBUG(oss.str());
return false; return false;
} }
} }

View File

@ -29,6 +29,7 @@
#include "StringComparison.h" #include "StringComparison.h"
#include <assimp/DefaultLogger.hpp> #include <assimp/DefaultLogger.hpp>
#include <assimp/Exceptional.h> #include <assimp/Exceptional.h>
#include <assimp/StringUtils.h>
#ifdef _MSC_VER #ifdef _MSC_VER
# include <stdint.h> # include <stdint.h>
@ -193,7 +194,7 @@ uint64_t strtoul10_64( const char* in, const char** out=0, unsigned int* max_ino
if ( *in < '0' || *in > '9' ) { if ( *in < '0' || *in > '9' ) {
// The string is known to be bad, so don't risk printing the whole thing. // The string is known to be bad, so don't risk printing the whole thing.
throw ExceptionType("The string \"", std::string(in).substr(0, 100), "\" cannot be converted into a value." ); throw ExceptionType("The string \"", ai_str_toprintable(in, 30), "\" cannot be converted into a value." );
} }
for ( ;; ) { for ( ;; ) {
@ -293,7 +294,7 @@ const char* fast_atoreal_move(const char* c, Real& out, bool check_comma = true)
if (!(c[0] >= '0' && c[0] <= '9') && if (!(c[0] >= '0' && c[0] <= '9') &&
!((c[0] == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')) { !((c[0] == '.' || (check_comma && c[0] == ',')) && c[1] >= '0' && c[1] <= '9')) {
// The string is known to be bad, so don't risk printing the whole thing. // The string is known to be bad, so don't risk printing the whole thing.
throw ExceptionType("Cannot parse string \"", std::string(c).substr(0, 100), throw ExceptionType("Cannot parse string \"", ai_str_toprintable(c, 30),
"\" as a real number: does not start with digit " "\" as a real number: does not start with digit "
"or decimal point followed by digit."); "or decimal point followed by digit.");
} }

View File

@ -1,6 +1,6 @@
#-*- coding: utf-8 -*- #-*- coding: utf-8 -*-
from ctypes import POINTER, c_void_p, c_uint, c_char, c_float, Structure, c_char_p, c_double, c_ubyte, c_size_t, c_uint32 from ctypes import POINTER, c_void_p, c_uint, c_char, c_float, Structure, c_double, c_ubyte, c_size_t, c_uint32
class Vector2D(Structure): class Vector2D(Structure):
@ -1121,7 +1121,7 @@ class Scene(Structure):
("mMetadata", POINTER(Metadata)), ("mMetadata", POINTER(Metadata)),
# Internal data, do not touch # Internal data, do not touch
("mPrivate", c_char_p), ("mPrivate", POINTER(c_char)),
] ]
assimp_structs_as_tuple = (Matrix4x4, assimp_structs_as_tuple = (Matrix4x4,

View File

@ -42,22 +42,12 @@ void ModelLoader::Draw(ID3D11DeviceContext * devcon) {
} }
} }
std::string textype;
Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) { Mesh ModelLoader::processMesh(aiMesh * mesh, const aiScene * scene) {
// Data to fill // Data to fill
std::vector<VERTEX> vertices; std::vector<VERTEX> vertices;
std::vector<UINT> indices; std::vector<UINT> indices;
std::vector<Texture> textures; std::vector<Texture> textures;
if (mesh->mMaterialIndex >= 0) {
aiMaterial* mat = scene->mMaterials[mesh->mMaterialIndex];
if (textype.empty()) {
textype = determineTextureType(scene, mat);
}
}
// Walk through each of the mesh's vertices // Walk through each of the mesh's vertices
for (UINT i = 0; i < mesh->mNumVertices; i++) { for (UINT i = 0; i < mesh->mNumVertices; i++) {
VERTEX vertex; VERTEX vertex;
@ -108,9 +98,10 @@ std::vector<Texture> ModelLoader::loadMaterialTextures(aiMaterial * mat, aiTextu
if (!skip) { // If texture hasn't been loaded already, load it if (!skip) { // If texture hasn't been loaded already, load it
HRESULT hr; HRESULT hr;
Texture texture; Texture texture;
if (textype == "embedded compressed texture") {
int textureindex = getTextureIndex(&str); const aiTexture* embeddedTexture = scene->GetEmbeddedTexture(str.C_Str());
texture.texture = getTextureFromModel(scene, textureindex); if (embeddedTexture != nullptr) {
texture.texture = loadEmbeddedTexture(embeddedTexture);
} else { } else {
std::string filename = std::string(str.C_Str()); std::string filename = std::string(str.C_Str());
filename = directory_ + '/' + filename; filename = directory_ + '/' + filename;
@ -148,38 +139,46 @@ void ModelLoader::processNode(aiNode * node, const aiScene * scene) {
} }
} }
std::string ModelLoader::determineTextureType(const aiScene * scene, aiMaterial * mat) { ID3D11ShaderResourceView * ModelLoader::loadEmbeddedTexture(const aiTexture* embeddedTexture) {
aiString textypeStr;
mat->GetTexture(aiTextureType_DIFFUSE, 0, &textypeStr);
std::string textypeteststr = textypeStr.C_Str();
if (textypeteststr == "*0" || textypeteststr == "*1" || textypeteststr == "*2" || textypeteststr == "*3" || textypeteststr == "*4" || textypeteststr == "*5") {
if (scene->mTextures[0]->mHeight == 0) {
return "embedded compressed texture";
} else {
return "embedded non-compressed texture";
}
}
if (textypeteststr.find('.') != std::string::npos) {
return "textures are on disk";
}
return ".";
}
int ModelLoader::getTextureIndex(aiString * str) {
std::string tistr;
tistr = str->C_Str();
tistr = tistr.substr(1);
return stoi(tistr);
}
ID3D11ShaderResourceView * ModelLoader::getTextureFromModel(const aiScene * scene, int textureindex) {
HRESULT hr; HRESULT hr;
ID3D11ShaderResourceView *texture; ID3D11ShaderResourceView *texture = nullptr;
int* size = reinterpret_cast<int*>(&scene->mTextures[textureindex]->mWidth); if (embeddedTexture->mHeight != 0) {
// Load an uncompressed ARGB8888 embedded texture
D3D11_TEXTURE2D_DESC desc;
desc.Width = embeddedTexture->mWidth;
desc.Height = embeddedTexture->mHeight;
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.SampleDesc.Count = 1;
desc.SampleDesc.Quality = 0;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
desc.CPUAccessFlags = 0;
desc.MiscFlags = 0;
hr = CreateWICTextureFromMemory(dev_, devcon_, reinterpret_cast<unsigned char*>(scene->mTextures[textureindex]->pcData), *size, nullptr, &texture); D3D11_SUBRESOURCE_DATA subresourceData;
subresourceData.pSysMem = embeddedTexture->pcData;
subresourceData.SysMemPitch = embeddedTexture->mWidth * 4;
subresourceData.SysMemSlicePitch = embeddedTexture->mWidth * embeddedTexture->mHeight * 4;
ID3D11Texture2D *texture2D = nullptr;
hr = dev_->CreateTexture2D(&desc, &subresourceData, &texture2D);
if (FAILED(hr))
MessageBox(hwnd_, "CreateTexture2D failed!", "Error!", MB_ICONERROR | MB_OK);
hr = dev_->CreateShaderResourceView(texture2D, nullptr, &texture);
if (FAILED(hr))
MessageBox(hwnd_, "CreateShaderResourceView failed!", "Error!", MB_ICONERROR | MB_OK);
return texture;
}
// mHeight is 0, so try to load a compressed texture of mWidth bytes
const size_t size = embeddedTexture->mWidth;
hr = CreateWICTextureFromMemory(dev_, devcon_, reinterpret_cast<const unsigned char*>(embeddedTexture->pcData), size, nullptr, &texture);
if (FAILED(hr)) if (FAILED(hr))
MessageBox(hwnd_, "Texture couldn't be created from memory!", "Error!", MB_ICONERROR | MB_OK); MessageBox(hwnd_, "Texture couldn't be created from memory!", "Error!", MB_ICONERROR | MB_OK);

View File

@ -35,9 +35,7 @@ private:
void processNode(aiNode* node, const aiScene* scene); void processNode(aiNode* node, const aiScene* scene);
Mesh processMesh(aiMesh* mesh, const aiScene* scene); Mesh processMesh(aiMesh* mesh, const aiScene* scene);
std::vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, std::string typeName, const aiScene* scene); std::vector<Texture> loadMaterialTextures(aiMaterial* mat, aiTextureType type, std::string typeName, const aiScene* scene);
std::string determineTextureType(const aiScene* scene, aiMaterial* mat); ID3D11ShaderResourceView* loadEmbeddedTexture(const aiTexture* embeddedTexture);
int getTextureIndex(aiString* str);
ID3D11ShaderResourceView* getTextureFromModel(const aiScene* scene, int textureindex);
}; };
#endif // !MODEL_LOADER_H #endif // !MODEL_LOADER_H

BIN
test/test.3mf 100644

Binary file not shown.

View File

@ -42,9 +42,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/StringUtils.h> #include <assimp/StringUtils.h>
class utStringUtils : public ::testing::Test { class utStringUtils : public ::testing::Test {
// empty
}; };
TEST_F( utStringUtils, to_string_Test ) { TEST_F(utStringUtils, to_string_Test ) {
std::string res = ai_to_string( 1 ); std::string res = ai_to_string( 1 );
EXPECT_EQ( res, "1" ); EXPECT_EQ( res, "1" );
@ -52,7 +53,7 @@ TEST_F( utStringUtils, to_string_Test ) {
EXPECT_EQ( res, "1" ); EXPECT_EQ( res, "1" );
} }
TEST_F( utStringUtils, ai_strtofTest ) { TEST_F(utStringUtils, ai_strtofTest ) {
float res = ai_strtof( nullptr, nullptr ); float res = ai_strtof( nullptr, nullptr );
EXPECT_FLOAT_EQ( res, 0.0f ); EXPECT_FLOAT_EQ( res, 0.0f );
@ -66,3 +67,11 @@ TEST_F( utStringUtils, ai_strtofTest ) {
res = ai_strtof( begin, end ); res = ai_strtof( begin, end );
EXPECT_FLOAT_EQ( res, 200.0f ); EXPECT_FLOAT_EQ( res, 200.0f );
} }
TEST_F(utStringUtils, ai_rgba2hexTest) {
std::string result;
result = ai_rgba2hex(255, 255, 255, 255, true);
EXPECT_EQ(result, "#ffffffff");
result = ai_rgba2hex(0, 0, 0, 0, false);
EXPECT_EQ(result, "00000000");
}

View File

@ -130,8 +130,9 @@ int SaveAsBMP(FILE *file, const aiTexel *data, unsigned int width, unsigned int
s[0] = t->b; s[0] = t->b;
s[1] = t->g; s[1] = t->g;
s[2] = t->r; s[2] = t->r;
if (4 == numc) if (4 == numc) {
s[3] = t->a; s[3] = t->a;
}
} }
} }
@ -296,7 +297,7 @@ int Assimp_Extract(const char *const *params, unsigned int num) {
// check whether the requested texture is existing // check whether the requested texture is existing
if (texIdx >= scene->mNumTextures) { if (texIdx >= scene->mNumTextures) {
::printf("assimp extract: Texture %i requested, but there are just %i textures\n", ::printf("assimp extract: Texture %u requested, but there are just %i textures\n",
texIdx, scene->mNumTextures); texIdx, scene->mNumTextures);
return AssimpCmdExtractError::TextureIndexIsOutOfRange; return AssimpCmdExtractError::TextureIndexIsOutOfRange;
} }
@ -325,7 +326,7 @@ int Assimp_Extract(const char *const *params, unsigned int num) {
// if the texture is a compressed one, we'll export // if the texture is a compressed one, we'll export
// it to its native file format // it to its native file format
if (!tex->mHeight) { if (!tex->mHeight) {
printf("assimp extract: Texture %i is compressed (%s). Writing native file format.\n", printf("assimp extract: Texture %u is compressed (%s). Writing native file format.\n",
i, tex->achFormatHint); i, tex->achFormatHint);
// modify file extension // modify file extension
@ -350,7 +351,7 @@ int Assimp_Extract(const char *const *params, unsigned int num) {
} }
::fclose(p); ::fclose(p);
printf("assimp extract: Wrote texture %i to %s\n", i, out_cpy.c_str()); printf("assimp extract: Wrote texture %u to %s\n", i, out_cpy.c_str());
if (texIdx != 0xffffffff) { if (texIdx != 0xffffffff) {
return m; return m;
} }

View File

@ -272,7 +272,7 @@ bool CMaterialManager::TryLongerPath(char* szTemp,aiString* p_szString)
szExtFound - 1 - info.cFileName); szExtFound - 1 - info.cFileName);
for (unsigned int i = 0; i < iSizeFound;++i) for (unsigned int i = 0; i < iSizeFound;++i)
info.cFileName[i] = (CHAR)tolower(info.cFileName[i]); info.cFileName[i] = (CHAR)tolower((unsigned char)info.cFileName[i]);
if (0 == memcmp(info.cFileName,szFile2, std::min(iSizeFound,iSize))) if (0 == memcmp(info.cFileName,szFile2, std::min(iSizeFound,iSize)))
{ {
@ -354,7 +354,7 @@ int CMaterialManager::FindValidPath(aiString* p_szString)
for (unsigned int i = 0;;++i) for (unsigned int i = 0;;++i)
{ {
if ('\0' == szTemp[i])break; if ('\0' == szTemp[i])break;
szTemp[i] = (char)tolower(szTemp[i]); szTemp[i] = (char)tolower((unsigned char)szTemp[i]);
} }
if(TryLongerPath(szTemp,p_szString))return 1; if(TryLongerPath(szTemp,p_szString))return 1;