Merge branch 'master' into respect-cmake-output-variables

pull/4338/head
Kim Kulling 2022-01-23 18:11:47 +01:00 committed by GitHub
commit 6cc469a5ae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
67 changed files with 1270 additions and 737 deletions

View File

@ -111,20 +111,9 @@ Discreet3DSImporter::~Discreet3DSImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool Discreet3DSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
std::string extension = GetExtension(pFile);
if (extension == "3ds" || extension == "prj") {
return true;
}
if (!extension.length() || checkSig) {
uint16_t token[3];
token[0] = 0x4d4d;
token[1] = 0x3dc2;
//token[2] = 0x3daa;
return CheckMagicToken(pIOHandler, pFile, token, 2, 0, 2);
}
return false;
bool Discreet3DSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const uint16_t token[] = { 0x4d4d, 0x3dc2 /*, 0x3daa */ };
return CheckMagicToken(pIOHandler, pFile, token, AI_COUNT_OF(token), 0, sizeof token[0]);
}
// ------------------------------------------------------------------------------------------------

View File

@ -90,26 +90,14 @@ D3MFImporter::~D3MFImporter() {
// empty
}
bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension(GetExtension(filename));
if (extension == desc.mFileExtensions) {
return true;
}
if (!extension.length() || checkSig) {
if (nullptr == pIOHandler) {
return false;
}
bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool /*checkSig*/) const {
if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) {
return false;
}
D3MFOpcPackage opcPackage(pIOHandler, filename);
D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename);
return opcPackage.validate();
}
return false;
}
void D3MFImporter::SetupProperties(const Importer*) {
// empty
}

View File

@ -152,18 +152,9 @@ AC3DImporter::~AC3DImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool AC3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
std::string extension = GetExtension(pFile);
// fixme: are acc and ac3d *really* used? Some sources say they are
if (extension == "ac" || extension == "ac3d" || extension == "acc") {
return true;
}
if (!extension.length() || checkSig) {
uint32_t token = AI_MAKE_MAGIC("AC3D");
return CheckMagicToken(pIOHandler, pFile, &token, 1, 0);
}
return false;
bool AC3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const uint32_t tokens[] = { AI_MAKE_MAGIC("AC3D") };
return CheckMagicToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -503,19 +503,9 @@ void AMFImporter::ParseNode_Metadata(XmlNode &node) {
mNodeElement_List.push_back(ne); // and to node element list because its a new object in graph.
}
bool AMFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool pCheckSig) const {
const std::string extension = GetExtension(pFile);
if (extension == "amf") {
return true;
}
if (extension.empty() || pCheckSig) {
static const char * const tokens[] = { "<amf" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
return false;
bool AMFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*pCheckSig*/) const {
static const char *tokens[] = { "<amf" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
const aiImporterDesc *AMFImporter::GetInfo() const {

View File

@ -95,19 +95,9 @@ ASEImporter::~ASEImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool ASEImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool cs) const {
// check file extension
const std::string extension = GetExtension(pFile);
if (extension == "ase" || extension == "ask") {
return true;
}
if ((!extension.length() || cs) && pIOHandler) {
static const char * const tokens[] = { "*3dsmax_asciiexport" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
return false;
bool ASEImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const char *tokens[] = { "*3dsmax_asciiexport" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -486,8 +486,9 @@ void Parser::ParseLV1MaterialListBlock() {
ParseLV4MeshLong(iIndex);
if (iIndex >= iMaterialCount) {
LogWarning("Out of range: material index is too large");
LogError("Out of range: material index is too large");
iIndex = iMaterialCount - 1;
return;
}
// get a reference to the material

View File

@ -89,11 +89,11 @@ void DeleteAllBarePointers(std::vector<T> &x) {
}
B3DImporter::~B3DImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------
bool B3DImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
size_t pos = pFile.find_last_of('.');
if (pos == string::npos) {
return false;

View File

@ -92,18 +92,9 @@ BVHLoader::~BVHLoader() {}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool BVHLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool cs) const {
// check file extension
const std::string extension = GetExtension(pFile);
if (extension == "bvh")
return true;
if ((!extension.length() || cs) && pIOHandler) {
static const char * const tokens[] = { "HIERARCHY" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
return false;
bool BVHLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const char *tokens[] = { "HIERARCHY" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -114,22 +114,14 @@ BlenderImporter::~BlenderImporter() {
}
static const char * const Tokens[] = { "BLENDER" };
static const char * const TokensForSearch[] = { "blender" };
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool BlenderImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string &extension = GetExtension(pFile);
if (extension == "blend") {
return true;
}
if ((!extension.length() || checkSig) && pIOHandler) {
bool BlenderImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
// note: this won't catch compressed files
return SearchFileHeaderForToken(pIOHandler, pFile, TokensForSearch, 1);
}
static const char *tokens[] = { "<BLENDER", "blender" };
return false;
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -106,7 +106,18 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------
bool C4DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
C4DImporter::C4DImporter()
: BaseImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------
C4DImporter::~C4DImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------
bool C4DImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool /*checkSig*/) const {
const std::string& extension = GetExtension(pFile);
if (extension == "c4d") {
return true;

View File

@ -103,17 +103,9 @@ COBImporter::~COBImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool COBImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string &extension = GetExtension(pFile);
if (extension == "cob" || extension == "scn" || extension == "COB" || extension == "SCN") {
return true;
}
else if ((!extension.length() || checkSig) && pIOHandler) {
static const char * const tokens[] = { "Caligary" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
return false;
bool COBImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const char *tokens[] = { "Caligary" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -90,19 +90,10 @@ CSMImporter::~CSMImporter()
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool CSMImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
bool CSMImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const
{
// check file extension
const std::string extension = GetExtension(pFile);
if( extension == "csm")
return true;
if ((checkSig || !extension.length()) && pIOHandler) {
static const char * const tokens[] = {"$Filename"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
}
return false;
static const char* tokens[] = {"$Filename"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -116,37 +116,15 @@ ColladaLoader::~ColladaLoader() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
// check file extension
const std::string extension = GetExtension(pFile);
const bool readSig = checkSig && (pIOHandler != nullptr);
if (!readSig) {
if (extension == "dae" || extension == "zae") {
return true;
}
} else {
bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
// Look for a DAE file inside, but don't extract it
ZipArchiveIOSystem zip_archive(pIOHandler, pFile);
if (zip_archive.isOpen()) {
return !ColladaParser::ReadZaeManifest(zip_archive).empty();
}
}
// XML - too generic, we need to open the file and search for typical keywords
if (extension == "xml" || !extension.length() || checkSig) {
// If CanRead() is called in order to check whether we
// support a specific file extension in general pIOHandler
// might be nullptr and it's our duty to return true here.
if (nullptr == pIOHandler) {
return true;
}
static const char * const tokens[] = {
"<collada"
};
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
return false;
static const char *tokens[] = { "<collada" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -331,7 +331,16 @@ void ColladaParser::ReadAssetInfo(XmlNode &node) {
const std::string &currentName = currentNode.name();
if (currentName == "unit") {
mUnitSize = 1.f;
XmlParser::getRealAttribute(currentNode, "meter", mUnitSize);
std::string tUnitSizeString;
if (XmlParser::getStdStrAttribute(currentNode, "meter", tUnitSizeString)) {
try {
fast_atoreal_move<ai_real>(tUnitSizeString.data(), mUnitSize);
} catch (const DeadlyImportError& die) {
std::string warning("Collada: Failed to parse meter parameter to real number. Exception:\n");
warning.append(die.what());
ASSIMP_LOG_WARN(warning.data());
}
}
} else if (currentName == "up_axis") {
std::string v;
if (!XmlParser::getValueAsString(currentNode, v)) {
@ -2242,7 +2251,11 @@ void ColladaParser::ReadNodeGeometry(XmlNode &node, Node *pNode) {
if (currentName == "bind_material") {
XmlNode techNode = currentNode.child("technique_common");
if (techNode) {
XmlNode instanceMatNode = techNode.child("instance_material");
for (XmlNode instanceMatNode = techNode.child("instance_material"); instanceMatNode; instanceMatNode = instanceMatNode.next_sibling())
{
const std::string &instance_name = instanceMatNode.name();
if (instance_name == "instance_material")
{
// read ID of the geometry subgroup and the target material
std::string group;
XmlParser::getStdStrAttribute(instanceMatNode, "symbol", group);
@ -2259,6 +2272,8 @@ void ColladaParser::ReadNodeGeometry(XmlNode &node, Node *pNode) {
}
}
}
}
}
// store it
pNode->mMeshes.push_back(instance);

View File

@ -123,18 +123,9 @@ DXFImporter::~DXFImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool DXFImporter::CanRead( const std::string& filename, IOSystem* pIOHandler, bool checkSig ) const {
const std::string& extension = GetExtension( filename );
if ( extension == desc.mFileExtensions ) {
return true;
}
if ( extension.empty() || checkSig ) {
static const char * const pTokens[] = { "SECTION", "HEADER", "ENDSEC", "BLOCKS" };
return SearchFileHeaderForToken(pIOHandler, filename, pTokens, 4, 32 );
}
return false;
bool DXFImporter::CanRead( const std::string& filename, IOSystem* pIOHandler, bool /*checkSig*/ ) const {
static const char *tokens[] = { "SECTION", "HEADER", "ENDSEC", "BLOCKS" };
return SearchFileHeaderForToken(pIOHandler, filename, tokens, AI_COUNT_OF(tokens), 32);
}
// ------------------------------------------------------------------------------------------------

View File

@ -100,18 +100,10 @@ FBXImporter::~FBXImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool FBXImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string &extension = GetExtension(pFile);
if (extension == std::string(desc.mFileExtensions)) {
return true;
}
else if ((!extension.length() || checkSig) && pIOHandler) {
bool FBXImporter::CanRead(const std::string & pFile, IOSystem * pIOHandler, bool /*checkSig*/) const {
// at least ASCII-FBX files usually have a 'FBX' somewhere in their head
static const char * const tokens[] = { "fbx" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
return false;
static const char *tokens[] = { "fbx" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -84,20 +84,13 @@ HMPImporter::~HMPImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool HMPImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool cs) const {
const std::string extension = GetExtension(pFile);
if (extension == "hmp")
return true;
// if check for extension is not enough, check for the magic tokens
if (!extension.length() || cs) {
uint32_t tokens[3];
tokens[0] = AI_HMP_MAGIC_NUMBER_LE_4;
tokens[1] = AI_HMP_MAGIC_NUMBER_LE_5;
tokens[2] = AI_HMP_MAGIC_NUMBER_LE_7;
return CheckMagicToken(pIOHandler, pFile, tokens, 3, 0);
}
return false;
bool HMPImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const uint32_t tokens[] = {
AI_HMP_MAGIC_NUMBER_LE_4,
AI_HMP_MAGIC_NUMBER_LE_5,
AI_HMP_MAGIC_NUMBER_LE_7
};
return CheckMagicToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -699,7 +699,7 @@ void ProcessBooleanExtrudedAreaSolidDifference(const Schema_2x3::IfcExtrudedArea
continue;
}
GenerateOpenings(openings, std::vector<IfcVector3>(1, IfcVector3(1, 0, 0)), temp, false, true);
GenerateOpenings(openings, temp, false, true);
result.Append(temp);
vit += pcount;

View File

@ -190,7 +190,7 @@ void ProcessPolygonBoundaries(TempMesh& result, const TempMesh& inmesh, size_t m
std::copy(outer_vit, outer_vit+outer_polygon_size,
std::back_inserter(temp.mVerts));
GenerateOpenings(fake_openings, normals, temp, false, false);
GenerateOpenings(fake_openings, temp, false, false);
result.Append(temp);
}
@ -529,6 +529,31 @@ IfcMatrix3 DerivePlaneCoordinateSpace(const TempMesh& curmesh, bool& ok, IfcVect
return m;
}
const auto closeDistance = 1e-6;
bool areClose(Schema_2x3::IfcCartesianPoint pt1,Schema_2x3::IfcCartesianPoint pt2) {
if(pt1.Coordinates.size() != pt2.Coordinates.size())
{
IFCImporter::LogWarn("unable to compare differently-dimensioned points");
return false;
}
auto coord1 = pt1.Coordinates.begin();
auto coord2 = pt2.Coordinates.begin();
// we're just testing each dimension separately rather than doing euclidean distance, as we're
// looking for very close coordinates
for(; coord1 != pt1.Coordinates.end(); coord1++,coord2++)
{
if(std::fabs(*coord1 - *coord2) > closeDistance)
return false;
}
return true;
}
bool areClose(IfcVector3 pt1,IfcVector3 pt2) {
return (std::fabs(pt1.x - pt2.x) < closeDistance &&
std::fabs(pt1.y - pt2.y) < closeDistance &&
std::fabs(pt1.z - pt2.z) < closeDistance);
}
// Extrudes the given polygon along the direction, converts it into an opening or applies all openings as necessary.
void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const TempMesh& curve,
const IfcVector3& extrusionDir, TempMesh& result, ConversionData &conv, bool collect_openings)
@ -592,7 +617,21 @@ void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const Te
nors.push_back(IfcVector3());
continue;
}
nors.push_back(((bounds.mVerts[2] - bounds.mVerts[0]) ^ (bounds.mVerts[1] - bounds.mVerts[0])).Normalize());
auto nor = ((bounds.mVerts[2] - bounds.mVerts[0]) ^ (bounds.mVerts[1] - bounds.mVerts[0])).Normalize();
auto vI0 = bounds.mVertcnt[0];
for(size_t faceI = 0; faceI < bounds.mVertcnt.size(); faceI++)
{
if(bounds.mVertcnt[faceI] >= 3) {
// do a check that this is at least parallel to the base plane
auto nor2 = ((bounds.mVerts[vI0 + 2] - bounds.mVerts[vI0]) ^ (bounds.mVerts[vI0 + 1] - bounds.mVerts[vI0])).Normalize();
if(!areClose(nor,nor2)) {
std::stringstream msg;
msg << "Face " << faceI << " is not parallel with face 0 - opening on entity " << solid.GetID();
IFCImporter::LogWarn(msg.str().c_str());
}
}
}
nors.push_back(nor);
}
}
@ -613,7 +652,7 @@ void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const Te
out.push_back(in[i] + dir);
if( openings ) {
if( (in[i] - in[next]).Length() > diag * 0.1 && GenerateOpenings(*conv.apply_openings, nors, temp, true, true, dir) ) {
if( (in[i] - in[next]).Length() > diag * 0.1 && GenerateOpenings(*conv.apply_openings, temp, true, true, dir) ) {
++sides_with_openings;
}
@ -625,7 +664,9 @@ void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const Te
if(openings) {
for(TempOpening& opening : *conv.apply_openings) {
if(!opening.wallPoints.empty()) {
IFCImporter::LogError("failed to generate all window caps");
std::stringstream msg;
msg << "failed to generate all window caps on ID " << (int)solid.GetID();
IFCImporter::LogError(msg.str().c_str());
}
opening.wallPoints.clear();
}
@ -646,7 +687,7 @@ void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const Te
curmesh.mVertcnt.push_back(static_cast<unsigned int>(in.size()));
if(openings && in.size() > 2) {
if( GenerateOpenings(*conv.apply_openings, nors, temp, true, true, dir) ) {
if(GenerateOpenings(*conv.apply_openings,temp,true,true,dir)) {
++sides_with_v_openings;
}
@ -657,7 +698,9 @@ void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const Te
}
if (openings && (sides_with_openings == 1 || sides_with_v_openings == 2)) {
IFCImporter::LogWarn("failed to resolve all openings, presumably their topology is not supported by Assimp");
std::stringstream msg;
msg << "failed to resolve all openings, presumably their topology is not supported by Assimp - ID " << solid.GetID() << " sides_with_openings " << sides_with_openings << " sides_with_v_openings " << sides_with_v_openings;
IFCImporter::LogWarn(msg.str().c_str());
}
IFCImporter::LogVerboseDebug("generate mesh procedurally by extrusion (IfcExtrudedAreaSolid)");
@ -781,7 +824,9 @@ bool ProcessGeometricItem(const Schema_2x3::IfcRepresentationItem& geo, unsigned
return false;
}
else {
IFCImporter::LogWarn("skipping unknown IfcGeometricRepresentationItem entity, type is ", geo.GetClassName());
std::stringstream toLog;
toLog << "skipping unknown IfcGeometricRepresentationItem entity, type is " << geo.GetClassName() << " id is " << geo.GetID();
IFCImporter::LogWarn(toLog.str().c_str());
return false;
}

View File

@ -129,18 +129,12 @@ IFCImporter::~IFCImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool IFCImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string &extension = GetExtension(pFile);
if (extension == "ifc" || extension == "ifczip") {
return true;
} else if ((!extension.length() || checkSig) && pIOHandler) {
bool IFCImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
// note: this is the common identification for STEP-encoded files, so
// it is only unambiguous as long as we don't support any further
// file formats with STEP as their encoding.
static const char * const tokens[] = { "ISO-10303-21" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
return false;
static const char *tokens[] = { "ISO-10303-21" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -58,6 +58,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif
#include <iterator>
#include <forward_list>
#include <deque>
namespace Assimp {
namespace IFC {
@ -73,7 +75,7 @@ namespace Assimp {
// fallback method to generate wall openings
bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std::vector<IfcVector3>& nors,
bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
TempMesh& curmesh);
@ -1140,7 +1142,6 @@ IfcMatrix4 ProjectOntoPlane(std::vector<IfcVector2>& out_contour, const TempMesh
// ------------------------------------------------------------------------------------------------
bool GenerateOpenings(std::vector<TempOpening>& openings,
const std::vector<IfcVector3>& nors,
TempMesh& curmesh,
bool check_intersection,
bool generate_connection_geometry,
@ -1340,7 +1341,7 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
MergeWindowContours(temp_contour, other, poly);
if (poly.size() > 1) {
return TryAddOpenings_Poly2Tri(openings, nors, curmesh);
return TryAddOpenings_Poly2Tri(openings, curmesh);
}
else if (poly.size() == 0) {
IFCImporter::LogWarn("ignoring duplicate opening");
@ -1427,8 +1428,289 @@ bool GenerateOpenings(std::vector<TempOpening>& openings,
return true;
}
std::vector<IfcVector2> GetContourInPlane2D(std::shared_ptr<TempMesh> mesh,IfcMatrix3 planeSpace,
IfcVector3 planeNor,IfcFloat planeOffset,
IfcVector3 extrusionDir,IfcVector3& wall_extrusion,bool& first,bool& ok) {
std::vector<IfcVector2> contour;
const auto outernor = ((mesh->mVerts[2] - mesh->mVerts[0]) ^ (mesh->mVerts[1] - mesh->mVerts[0])).Normalize();
const IfcFloat dot = planeNor * outernor;
if(std::fabs(dot) < 1.f - 1e-6f) {
std::stringstream msg;
msg << "Skipping: Unaligned opening (" << planeNor.x << ", " << planeNor.y << ", " << planeNor.z << ")";
msg << " . ( " << outernor.x << ", " << outernor.y << ", " << outernor.z << ") = " << dot;
IFCImporter::LogDebug(msg.str().c_str());
ok = false;
return contour;
}
const std::vector<IfcVector3>& va = mesh->mVerts;
if(va.size() <= 2) {
std::stringstream msg;
msg << "Skipping: Only " << va.size() << " verticies in opening mesh.";
IFCImporter::LogDebug(msg.str().c_str());
ok = false;
return contour;
}
for(const IfcVector3& xx : mesh->mVerts) {
IfcVector3 vv = planeSpace * xx,vv_extr = planeSpace * (xx + extrusionDir);
const bool is_extruded_side = std::fabs(vv.z - planeOffset) > std::fabs(vv_extr.z - planeOffset);
if(first) {
first = false;
if(dot > 0.f) {
wall_extrusion = extrusionDir;
if(is_extruded_side) {
wall_extrusion = -wall_extrusion;
}
}
}
// XXX should not be necessary - but it is. Why? For precision reasons?
vv = is_extruded_side ? vv_extr : vv;
contour.push_back(IfcVector2(vv.x,vv.y));
}
ok = true;
return contour;
}
const float close { 1e-6f };
static bool isClose(IfcVector2 first,IfcVector2 second) {
auto diff = (second - first);
return (std::fabs(diff.x) < close && std::fabs(diff.y) < close);
}
static void logSegment(std::pair<IfcVector2,IfcVector2> segment) {
std::stringstream msg2;
msg2 << " Segment: \n";
msg2 << " " << segment.first.x << " " << segment.first.y << " \n";
msg2 << " " << segment.second.x << " " << segment.second.y << " \n";
IFCImporter::LogInfo(msg2.str().c_str());
}
std::vector<std::vector<IfcVector2>> GetContoursInPlane3D(std::shared_ptr<TempMesh> mesh,IfcMatrix3 planeSpace,
IfcFloat planeOffset) {
{
std::stringstream msg;
msg << "GetContoursInPlane3D: planeSpace is \n";
msg << planeSpace.a1 << " " << planeSpace.a2 << " " << planeSpace.a3 << " " << "\n";
msg << planeSpace.b1 << " " << planeSpace.b2 << " " << planeSpace.b3 << " " << "\n";
msg << planeSpace.c1 << " " << planeSpace.c2 << " " << planeSpace.c3 << " " << "\n";
msg << "\n planeOffset is " << planeOffset;
IFCImporter::LogInfo(msg.str().c_str());
}
// we'll put our line segments in here, and then merge them together into contours later
std::deque<std::pair<IfcVector2,IfcVector2>> lineSegments;
// find the lines giving the intersection of the faces with the plane - we'll work in planeSpace throughout.
size_t vI0{ 0 }; // vertex index for first vertex in plane
for(auto nVertices : mesh->mVertcnt) { // iterate over faces
{
std::stringstream msg;
msg << "GetContoursInPlane3D: face (transformed) is \n";
for(auto vI = vI0; vI < vI0 + nVertices; vI++) {
auto v = planeSpace * mesh->mVerts[vI];
msg << " " << v.x << " " << v.y << " " << v.z << " " << "\n";
}
IFCImporter::LogInfo(msg.str().c_str());
}
if(nVertices <= 2) // not a plane, a point or line
{
std::stringstream msg;
msg << "GetContoursInPlane3D: found point or line when expecting plane (only " << nVertices << " vertices)";
IFCImporter::LogWarn(msg.str().c_str());
vI0 += nVertices;
continue;
}
auto v0 = planeSpace * mesh->mVerts[vI0];
// now calculate intersections between face and plane
IfcVector2 firstPoint;
bool gotFirstPoint(false);
if(std::fabs(v0.z - planeOffset) < close) {
// first point is on the plane
firstPoint.x = v0.x;
firstPoint.y = v0.y;
gotFirstPoint = true;
}
auto vn = v0;
for(auto vI = vI0 + 1; vI < vI0 + nVertices; vI++) {
auto vp = vn;
vn = planeSpace * mesh->mVerts[vI];
IfcVector3 intersection;
if(std::fabs(vn.z - planeOffset) < close) {
// on the plane
intersection = vn;
}
else if((vn.z > planeOffset) != (vp.z > planeOffset))
{
// passes through the plane
auto vdir = vn - vp;
auto scale = (planeOffset - vp.z) / vdir.z;
intersection = vp + scale * vdir;
}
else {
// nowhere near - move on
continue;
}
if(!gotFirstPoint) {
if(std::fabs(vp.z - planeOffset) < close) {
// just had a second line along the plane
firstPoint.x = vp.x;
firstPoint.y = vp.y;
IfcVector2 secondPoint(intersection.x,intersection.y);
auto s = std::pair<IfcVector2,IfcVector2>(firstPoint,secondPoint);
logSegment(s);
lineSegments.push_back(s);
// next firstpoint should be this one
}
else {
// store the first intersection point
firstPoint.x = intersection.x;
firstPoint.y = intersection.y;
gotFirstPoint = true;
}
}
else {
// now got the second point, so store the pair
IfcVector2 secondPoint(intersection.x,intersection.y);
auto s = std::pair<IfcVector2,IfcVector2>(firstPoint,secondPoint);
logSegment(s);
lineSegments.push_back(s);
// - note that we don't move onto the next face as a non-convex face can create two or more intersections with a plane
gotFirstPoint = false;
}
}
if(gotFirstPoint) {
IFCImporter::LogWarn("GetContoursInPlane3D: odd number of intersections with plane");
}
vI0 += nVertices;
}
{
std::stringstream msg;
msg << "GetContoursInPlane3D: found " << lineSegments.size() << " line segments:\n";
IFCImporter::LogInfo(msg.str().c_str());
for(auto& s : lineSegments) {
logSegment(s);
}
}
// now merge contours until we have the best-looking polygons we can
std::vector<Contour> contours;
while(!lineSegments.empty()) {
// start with a polygon and make the best closed contour we can
const auto& firstSeg = lineSegments.front();
std::deque<IfcVector2> contour{ firstSeg.first, firstSeg.second };
lineSegments.pop_front();
bool foundNextPoint{ true };
bool closedContour{ false };
while(foundNextPoint) {
foundNextPoint = false;
for(auto nextSeg = lineSegments.begin(); nextSeg != lineSegments.end(); nextSeg++) {
// see if we can match up both ends - in which case we've closed the contour
if((isClose(contour.front(),nextSeg->first) && isClose(contour.back(),nextSeg->second)) ||
(isClose(contour.back(),nextSeg->first) && isClose(contour.front(),nextSeg->second))
) {
lineSegments.erase(nextSeg);
closedContour = true;
break;
}
// otherwise, see if we can match up either end
foundNextPoint = true;
if(isClose(contour.front(),nextSeg->first)) {
contour.push_front(nextSeg->second);
}
else if(isClose(contour.front(),nextSeg->second)) {
contour.push_front(nextSeg->first);
}
else if(isClose(contour.back(),nextSeg->first)) {
contour.push_back(nextSeg->second);
}
else if(isClose(contour.back(),nextSeg->second)) {
contour.push_back(nextSeg->first);
}
else {
foundNextPoint = false;
}
if(foundNextPoint) {
lineSegments.erase(nextSeg);
break;
}
}
}
if(!closedContour) {
IFCImporter::LogWarn("GetContoursInPlane3D: did not close contour");
}
// now add the contour if we can
if(contour.size() <= 2) {
IFCImporter::LogWarn("GetContoursInPlane3D: discarding line/point contour");
continue;
}
Contour c{};
for(auto p : contour)
{
c.push_back(p);
}
contours.push_back(c);
}
{
std::stringstream msg;
msg << "GetContoursInPlane3D: found " << contours.size() << " contours:\n";
for(auto c : contours) {
msg << " Contour: \n";
for(auto p : c) {
msg << " " << p.x << " " << p.y << " \n";
}
}
IFCImporter::LogInfo(msg.str().c_str());
}
return contours;
}
std::vector<std::vector<IfcVector2>> GetContoursInPlane(std::shared_ptr<TempMesh> mesh,IfcMatrix3 planeSpace,
IfcVector3 planeNor,IfcFloat planeOffset,
IfcVector3 extrusionDir,IfcVector3& wall_extrusion,bool& first) {
if(mesh->mVertcnt.size() == 1)
{
bool ok;
auto contour = GetContourInPlane2D(mesh,planeSpace,planeNor,planeOffset,extrusionDir,wall_extrusion,first,ok);
if(ok)
return std::vector<std::vector<IfcVector2>> {contour};
else
return std::vector<std::vector<IfcVector2>> {};
}
else
{
return GetContoursInPlane3D(mesh,planeSpace,planeOffset);
}
}
// ------------------------------------------------------------------------------------------------
bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std::vector<IfcVector3>& nors,
bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,
TempMesh& curmesh)
{
IFCImporter::LogWarn("forced to use poly2tri fallback method to generate wall openings");
@ -1498,41 +1780,12 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
try {
ClipperLib::Clipper clipper_holes;
size_t c = 0;
for(const TempOpening& t : openings) {
const IfcVector3& outernor = nors[c++];
const IfcFloat dot = nor * outernor;
if (std::fabs(dot)<1.f-1e-6f) {
continue;
}
const std::vector<IfcVector3>& va = t.profileMesh->mVerts;
if(va.size() <= 2) {
continue;
}
std::vector<IfcVector2> contour;
for(const IfcVector3& xx : t.profileMesh->mVerts) {
IfcVector3 vv = m * xx, vv_extr = m * (xx + t.extrusionDir);
const bool is_extruded_side = std::fabs(vv.z - coord) > std::fabs(vv_extr.z - coord);
if (first) {
first = false;
if (dot > 0.f) {
wall_extrusion = t.extrusionDir;
if (is_extruded_side) {
wall_extrusion = - wall_extrusion;
}
}
}
// XXX should not be necessary - but it is. Why? For precision reasons?
vv = is_extruded_side ? vv_extr : vv;
contour.push_back(IfcVector2(vv.x,vv.y));
}
auto contours = GetContoursInPlane(t.profileMesh,m,nor,coord,t.extrusionDir,wall_extrusion,first);
for(auto& contour : contours) {
// scale to clipping space
ClipperLib::Polygon hole;
for(IfcVector2& pip : contour) {
pip.x = (pip.x - vmin.x) / vmax.x;
@ -1553,6 +1806,15 @@ bool TryAddOpenings_Poly2Tri(const std::vector<TempOpening>& openings,const std:
hole = pol_temp2[0];*/
clipper_holes.AddPolygon(hole,ClipperLib::ptSubject);
{
std::stringstream msg;
msg << "- added polygon ";
for(auto elem : hole) {
msg << " (" << elem.X << ", " << elem.Y << ")";
}
IFCImporter::LogDebug(msg.str().c_str());
}
}
}
clipper_holes.Execute(ClipperLib::ctUnion,holes_union,

View File

@ -307,7 +307,6 @@ void ProcessBooleanExtrudedAreaSolidDifference(const Schema_2x3::IfcExtrudedArea
// IFCOpenings.cpp
bool GenerateOpenings(std::vector<TempOpening>& openings,
const std::vector<IfcVector3>& nors,
TempMesh& curmesh,
bool check_intersection,
bool generate_connection_geometry,

View File

@ -0,0 +1,322 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2021, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#ifndef ASSIMP_BUILD_NO_IQM_IMPORTER
#include <assimp/DefaultIOSystem.h>
#include <assimp/IOStreamBuffer.h>
#include <assimp/ai_assert.h>
#include <assimp/importerdesc.h>
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <assimp/Importer.hpp>
#include <assimp/ByteSwapper.h>
#include <memory>
#include <numeric>
#include "IQMImporter.h"
#include "iqm.h"
// RESOURCES:
// http://sauerbraten.org/iqm/
// https://github.com/lsalzman/iqm
inline void swap_block( uint32_t *block, size_t size ){
(void)block; // suppress 'unreferenced formal parameter' MSVC warning
size >>= 2;
for ( size_t i = 0; i < size; ++i )
AI_SWAP4( block[ i ] );
}
static const aiImporterDesc desc = {
"Inter-Quake Model Importer",
"",
"",
"",
aiImporterFlags_SupportBinaryFlavour,
0,
0,
0,
0,
"iqm"
};
namespace Assimp {
// ------------------------------------------------------------------------------------------------
// Default constructor
IQMImporter::IQMImporter() :
mScene(nullptr) {
// empty
}
// ------------------------------------------------------------------------------------------------
// Returns true, if file is a binary Inter-Quake Model file.
bool IQMImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(pFile);
if (extension == "iqm")
return true;
else if (!extension.length() || checkSig) {
if (!pIOHandler) {
return true;
}
/*
* don't use CheckMagicToken because that checks with swapped bytes too, leading to false
* positives. This magic is not uint32_t, but char[4], so memcmp is the best way
const char* tokens[] = {"3DMO", "3dmo"};
return CheckMagicToken(pIOHandler,pFile,tokens,2,0,4);
*/
std::unique_ptr<IOStream> pStream(pIOHandler->Open(pFile, "rb"));
unsigned char data[15];
if (!pStream || 15 != pStream->Read(data, 1, 15)) {
return false;
}
return !memcmp(data, "INTERQUAKEMODEL", 15);
}
return false;
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc *IQMImporter::GetInfo() const {
return &desc;
}
// ------------------------------------------------------------------------------------------------
// Model 3D import implementation
void IQMImporter::InternReadFile(const std::string &file, aiScene *pScene, IOSystem *pIOHandler) {
// Read file into memory
std::unique_ptr<IOStream> pStream(pIOHandler->Open(file, "rb"));
if (!pStream.get()) {
throw DeadlyImportError("Failed to open file ", file, ".");
}
// Get the file-size and validate it, throwing an exception when fails
const size_t fileSize = pStream->FileSize();
if (fileSize < sizeof( iqmheader )) {
throw DeadlyImportError("IQM-file ", file, " is too small.");
}
std::vector<unsigned char> buffer(fileSize);
unsigned char *data = buffer.data();
if (fileSize != pStream->Read(data, 1, fileSize)) {
throw DeadlyImportError("Failed to read the file ", file, ".");
}
// get header
iqmheader &hdr = reinterpret_cast<iqmheader&>( *data );
swap_block( &hdr.version, sizeof( iqmheader ) - sizeof( iqmheader::magic ) );
// extra check for header
if (memcmp(data, IQM_MAGIC, sizeof( IQM_MAGIC ) )
|| hdr.version != IQM_VERSION
|| hdr.filesize != fileSize) {
throw DeadlyImportError("Bad binary header in file ", file, ".");
}
ASSIMP_LOG_DEBUG("IQM: loading ", file);
// create the root node
pScene->mRootNode = new aiNode( "<IQMRoot>" );
// 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);
pScene->mRootNode->mNumMeshes = hdr.num_meshes;
pScene->mRootNode->mMeshes = new unsigned int[hdr.num_meshes];
std::iota( pScene->mRootNode->mMeshes, pScene->mRootNode->mMeshes + pScene->mRootNode->mNumMeshes, 0 );
mScene = pScene;
// Allocate output storage
pScene->mNumMeshes = 0;
pScene->mMeshes = new aiMesh *[hdr.num_meshes](); // Set arrays to zero to ensue proper destruction if an exception is raised
pScene->mNumMaterials = 0;
pScene->mMaterials = new aiMaterial *[hdr.num_meshes]();
// swap vertex arrays beforehand...
for( auto array = reinterpret_cast<iqmvertexarray*>( data + hdr.ofs_vertexarrays ), end = array + hdr.num_vertexarrays; array != end; ++array )
{
swap_block( &array->type, sizeof( iqmvertexarray ) );
}
// Read all surfaces from the file
for( auto imesh = reinterpret_cast<iqmmesh*>( data + hdr.ofs_meshes ), end_ = imesh + hdr.num_meshes; imesh != end_; ++imesh )
{
swap_block( &imesh->name, sizeof( iqmmesh ) );
// Allocate output mesh & material
auto mesh = pScene->mMeshes[pScene->mNumMeshes++] = new aiMesh();
mesh->mMaterialIndex = pScene->mNumMaterials;
auto mat = pScene->mMaterials[pScene->mNumMaterials++] = new aiMaterial();
{
auto text = reinterpret_cast<char*>( data + hdr.ofs_text );
aiString name( text + imesh->material );
mat->AddProperty( &name, AI_MATKEY_NAME );
mat->AddProperty( &name, AI_MATKEY_TEXTURE_DIFFUSE(0) );
}
// Fill mesh information
mesh->mPrimitiveTypes = aiPrimitiveType_TRIANGLE;
mesh->mNumFaces = 0;
mesh->mFaces = new aiFace[imesh->num_triangles];
// Fill in all triangles
for( auto tri = reinterpret_cast<iqmtriangle*>( data + hdr.ofs_triangles ) + imesh->first_triangle, end = tri + imesh->num_triangles; tri != end; ++tri )
{
swap_block( tri->vertex, sizeof( tri->vertex ) );
auto& face = mesh->mFaces[mesh->mNumFaces++];
face.mNumIndices = 3;
face.mIndices = new unsigned int[3]{ tri->vertex[0] - imesh->first_vertex,
tri->vertex[2] - imesh->first_vertex,
tri->vertex[1] - imesh->first_vertex };
}
// Fill in all vertices
for( auto array = reinterpret_cast<const iqmvertexarray*>( data + hdr.ofs_vertexarrays ), end__ = array + hdr.num_vertexarrays; array != end__; ++array )
{
const unsigned int nVerts = imesh->num_vertexes;
const unsigned int step = array->size;
switch ( array->type )
{
case IQM_POSITION:
if( array->format == IQM_FLOAT && step >= 3 ){
mesh->mNumVertices = nVerts;
auto v = mesh->mVertices = new aiVector3D[nVerts];
for( auto f = reinterpret_cast<const float*>( data + array->offset ) + imesh->first_vertex * step,
end = f + nVerts * step; f != end; f += step, ++v )
{
*v = { AI_BE( f[0] ),
AI_BE( f[1] ),
AI_BE( f[2] ) };
}
}
break;
case IQM_TEXCOORD:
if( array->format == IQM_FLOAT && step >= 2)
{
auto v = mesh->mTextureCoords[0] = new aiVector3D[nVerts];
mesh->mNumUVComponents[0] = 2;
for( auto f = reinterpret_cast<const float*>( data + array->offset ) + imesh->first_vertex * step,
end = f + nVerts * step; f != end; f += step, ++v )
{
*v = { AI_BE( f[0] ),
1 - AI_BE( f[1] ), 0 };
}
}
break;
case IQM_NORMAL:
if (array->format == IQM_FLOAT && step >= 3)
{
auto v = mesh->mNormals = new aiVector3D[nVerts];
for( auto f = reinterpret_cast<const float*>( data + array->offset ) + imesh->first_vertex * step,
end = f + nVerts * step; f != end; f += step, ++v )
{
*v = { AI_BE( f[0] ),
AI_BE( f[1] ),
AI_BE( f[2] ) };
}
}
break;
case IQM_COLOR:
if (array->format == IQM_UBYTE && step >= 3)
{
auto v = mesh->mColors[0] = new aiColor4D[nVerts];
for( auto f = ( data + array->offset ) + imesh->first_vertex * step,
end = f + nVerts * step; f != end; f += step, ++v )
{
*v = { ( f[0] ) / 255.f,
( f[1] ) / 255.f,
( f[2] ) / 255.f,
step == 3? 1 : ( f[3] ) / 255.f };
}
}
else if (array->format == IQM_FLOAT && step >= 3)
{
auto v = mesh->mColors[0] = new aiColor4D[nVerts];
for( auto f = reinterpret_cast<const float*>( data + array->offset ) + imesh->first_vertex * step,
end = f + nVerts * step; f != end; f += step, ++v )
{
*v = { AI_BE( f[0] ),
AI_BE( f[1] ),
AI_BE( f[2] ),
step == 3? 1 : AI_BE( f[3] ) };
}
}
break;
case IQM_TANGENT:
#if 0
if (array->format == IQM_FLOAT && step >= 3)
{
auto v = mesh->mTangents = new aiVector3D[nVerts];
for( auto f = reinterpret_cast<const float*>( data + array->offset ) + imesh->first_vertex * step,
end = f + nVerts * step; f != end; f += step, ++v )
{
*v = { AI_BE( f[0] ),
AI_BE( f[1] ),
AI_BE( f[2] ) };
}
}
#endif
break;
case IQM_BLENDINDEXES:
case IQM_BLENDWEIGHTS:
case IQM_CUSTOM:
break; // these attributes are not relevant.
default:
break;
}
}
}
}
// ------------------------------------------------------------------------------------------------
} // Namespace Assimp
#endif // !! ASSIMP_BUILD_NO_IQM_IMPORTER

View File

@ -0,0 +1,78 @@
/*
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2021, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
with or without modification, are permitted provided that the
following conditions are met:
* Redistributions of source code must retain the above
copyright notice, this list of conditions and the
following disclaimer.
* Redistributions in binary form must reproduce the above
copyright notice, this list of conditions and the
following disclaimer in the documentation and/or other
materials provided with the distribution.
* Neither the name of the assimp team, nor the names of its
contributors may be used to endorse or promote products
derived from this software without specific prior
written permission of the assimp team.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
/** @file IQMImporter.h
* @brief Declares the importer class to read a scene from an Inter-Quake Model file
*/
#pragma once
#ifndef ASSIMP_BUILD_NO_IQM_IMPORTER
#include <assimp/BaseImporter.h>
#include <assimp/material.h>
namespace Assimp {
class IQMImporter : public BaseImporter {
public:
/// \brief Default constructor
IQMImporter();
~IQMImporter() override {}
/// \brief Returns whether the class can handle the format of the given file.
/// \remark See BaseImporter::CanRead() for details.
bool CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const override;
protected:
//! \brief Appends the supported extension.
const aiImporterDesc *GetInfo() const override;
//! \brief File import implementation.
void InternReadFile(const std::string &pFile, aiScene *pScene, IOSystem *pIOHandler) override;
private:
aiScene *mScene = nullptr; // the scene to import to
};
} // Namespace Assimp
#endif // ASSIMP_BUILD_NO_IQM_IMPORTER

View File

@ -0,0 +1,134 @@
#ifndef __IQM_H__
#define __IQM_H__
#define IQM_MAGIC "INTERQUAKEMODEL"
#define IQM_VERSION 2
struct iqmheader
{
char magic[16];
unsigned int version;
unsigned int filesize;
unsigned int flags;
unsigned int num_text, ofs_text;
unsigned int num_meshes, ofs_meshes;
unsigned int num_vertexarrays, num_vertexes, ofs_vertexarrays;
unsigned int num_triangles, ofs_triangles, ofs_adjacency;
unsigned int num_joints, ofs_joints;
unsigned int num_poses, ofs_poses;
unsigned int num_anims, ofs_anims;
unsigned int num_frames, num_framechannels, ofs_frames, ofs_bounds;
unsigned int num_comment, ofs_comment;
unsigned int num_extensions, ofs_extensions;
};
struct iqmmesh
{
unsigned int name;
unsigned int material;
unsigned int first_vertex, num_vertexes;
unsigned int first_triangle, num_triangles;
};
enum
{
IQM_POSITION = 0,
IQM_TEXCOORD = 1,
IQM_NORMAL = 2,
IQM_TANGENT = 3,
IQM_BLENDINDEXES = 4,
IQM_BLENDWEIGHTS = 5,
IQM_COLOR = 6,
IQM_CUSTOM = 0x10
};
enum
{
IQM_BYTE = 0,
IQM_UBYTE = 1,
IQM_SHORT = 2,
IQM_USHORT = 3,
IQM_INT = 4,
IQM_UINT = 5,
IQM_HALF = 6,
IQM_FLOAT = 7,
IQM_DOUBLE = 8
};
struct iqmtriangle
{
unsigned int vertex[3];
};
struct iqmadjacency
{
unsigned int triangle[3];
};
struct iqmjointv1
{
unsigned int name;
int parent;
float translate[3], rotate[3], scale[3];
};
struct iqmjoint
{
unsigned int name;
int parent;
float translate[3], rotate[4], scale[3];
};
struct iqmposev1
{
int parent;
unsigned int mask;
float channeloffset[9];
float channelscale[9];
};
struct iqmpose
{
int parent;
unsigned int mask;
float channeloffset[10];
float channelscale[10];
};
struct iqmanim
{
unsigned int name;
unsigned int first_frame, num_frames;
float framerate;
unsigned int flags;
};
enum
{
IQM_LOOP = 1<<0
};
struct iqmvertexarray
{
unsigned int type;
unsigned int flags;
unsigned int format;
unsigned int size;
unsigned int offset;
};
struct iqmbounds
{
float bbmin[3], bbmax[3];
float xyradius, radius;
};
struct iqmextension
{
unsigned int name;
unsigned int num_data, ofs_data;
unsigned int ofs_extensions; // pointer to next extension
};
#endif

View File

@ -94,23 +94,9 @@ IRRImporter::~IRRImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool IRRImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(pFile);
if (extension == "irr") {
return true;
} else if (extension == "xml" || checkSig) {
/* If CanRead() is called in order to check whether we
* support a specific file extension in general pIOHandler
* might be nullptr and it's our duty to return true here.
*/
if (nullptr == pIOHandler) {
return true;
}
static const char * const tokens[] = { "irr_scene" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
return false;
bool IRRImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const char *tokens[] = { "irr_scene" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -85,26 +83,14 @@ IRRMeshImporter::~IRRMeshImporter() {}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool IRRMeshImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
bool IRRMeshImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
/* NOTE: A simple check for the file extension is not enough
* here. Irrmesh and irr are easy, but xml is too generic
* and could be collada, too. So we need to open the file and
* search for typical tokens.
*/
const std::string extension = GetExtension(pFile);
if (extension == "irrmesh")
return true;
else if (extension == "xml" || checkSig) {
/* If CanRead() is called to check whether the loader
* supports a specific file extension in general we
* must return true here.
*/
if (!pIOHandler) return true;
static const char * const tokens[] = { "irrmesh" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
return false;
static const char *tokens[] = { "irrmesh" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -105,21 +105,13 @@ LWOImporter::~LWOImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool LWOImporter::CanRead(const std::string &file, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(file);
if (extension == "lwo" || extension == "lxo") {
return true;
}
// if check for extension is not enough, check for the magic tokens
if (!extension.length() || checkSig) {
uint32_t tokens[3];
tokens[0] = AI_LWO_FOURCC_LWOB;
tokens[1] = AI_LWO_FOURCC_LWO2;
tokens[2] = AI_LWO_FOURCC_LXOB;
return CheckMagicToken(pIOHandler, file, tokens, 3, 8);
}
return false;
bool LWOImporter::CanRead(const std::string &file, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const uint32_t tokens[] = {
AI_LWO_FOURCC_LWOB,
AI_LWO_FOURCC_LWO2,
AI_LWO_FOURCC_LXOB
};
return CheckMagicToken(pIOHandler, file, tokens, AI_COUNT_OF(tokens), 8);
}
// ------------------------------------------------------------------------------------------------

View File

@ -147,20 +147,12 @@ LWSImporter::~LWSImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool LWSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(pFile);
if (extension == "lws" || extension == "mot") {
return true;
}
// if check for extension is not enough, check for the magic tokens LWSC and LWMO
if (!extension.length() || checkSig) {
uint32_t tokens[2];
tokens[0] = AI_MAKE_MAGIC("LWSC");
tokens[1] = AI_MAKE_MAGIC("LWMO");
return CheckMagicToken(pIOHandler, pFile, tokens, 2);
}
return false;
bool LWSImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const uint32_t tokens[] = {
AI_MAKE_MAGIC("LWSC"),
AI_MAKE_MAGIC("LWMO")
};
return CheckMagicToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -111,35 +111,20 @@ M3DImporter::M3DImporter() :
// ------------------------------------------------------------------------------------------------
// Returns true, if file is a binary or ASCII Model 3D file.
bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(pFile);
if (extension == "m3d"
|| extension == "a3d"
)
return true;
else if (!extension.length() || checkSig) {
if (!pIOHandler) {
return true;
}
/*
* don't use CheckMagicToken because that checks with swapped bytes too, leading to false
* positives. This magic is not uint32_t, but char[4], so memcmp is the best way
const char* tokens[] = {"3DMO", "3dmo"};
return CheckMagicToken(pIOHandler,pFile,tokens,2,0,4);
*/
bool M3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
// don't use CheckMagicToken because that checks with swapped bytes too, leading to false
// positives. This magic is not uint32_t, but char[4], so memcmp is the best way
std::unique_ptr<IOStream> pStream(pIOHandler->Open(pFile, "rb"));
unsigned char data[4];
if (!pStream || 4 != pStream->Read(data, 1, 4)) {
if (4 != pStream->Read(data, 1, 4)) {
return false;
}
return !memcmp(data, "3DMO", 4) /* bin */
#ifdef M3D_ASCII
|| !memcmp(data, "3dmo", 4) /* ASCII */
#endif
;
}
return false;
}
// ------------------------------------------------------------------------------------------------
const aiImporterDesc *M3DImporter::GetInfo() const {

View File

@ -107,19 +107,10 @@ MD2Importer::~MD2Importer()
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool MD2Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
bool MD2Importer::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const
{
const std::string extension = GetExtension(pFile);
if (extension == "md2")
return true;
// if check for extension is not enough, check for the magic tokens
if (!extension.length() || checkSig) {
uint32_t tokens[1];
tokens[0] = AI_MD2_MAGIC_NUMBER_LE;
return CheckMagicToken(pIOHandler,pFile,tokens,1);
}
return false;
static const uint32_t tokens[] = { AI_MD2_MAGIC_NUMBER_LE };
return CheckMagicToken(pIOHandler,pFile,tokens,AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -349,18 +349,9 @@ MD3Importer::~MD3Importer() {}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool MD3Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(pFile);
if (extension == "md3")
return true;
// if check for extension is not enough, check for the magic tokens
if (!extension.length() || checkSig) {
uint32_t tokens[1];
tokens[0] = AI_MD3_MAGIC_NUMBER_LE;
return CheckMagicToken(pIOHandler, pFile, tokens, 1);
}
return false;
bool MD3Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const uint32_t tokens[] = { AI_MD3_MAGIC_NUMBER_LE };
return CheckMagicToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -100,20 +100,9 @@ MD5Importer::~MD5Importer() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool MD5Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(pFile);
if (extension == "md5anim" || extension == "md5mesh" || extension == "md5camera")
return true;
else if (!extension.length() || checkSig) {
if (!pIOHandler) {
return true;
}
static const char * const tokens[] = { "MD5Version" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
return false;
bool MD5Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const char *tokens[] = { "MD5Version" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -111,19 +111,9 @@ MDCImporter::~MDCImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool MDCImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(pFile);
if (extension == "mdc") {
return true;
}
// if check for extension is not enough, check for the magic tokens
if (!extension.length() || checkSig) {
uint32_t tokens[1];
tokens[0] = AI_MDC_MAGIC_NUMBER_LE;
return CheckMagicToken(pIOHandler, pFile, tokens, 1);
}
return false;
bool MDCImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const uint32_t tokens[] = { AI_MDC_MAGIC_NUMBER_LE };
return CheckMagicToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -104,23 +104,18 @@ MDLImporter::~MDLImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool MDLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(pFile);
// if check for extension is not enough, check for the magic tokens
if (extension == "mdl" || !extension.length() || checkSig) {
uint32_t tokens[8];
tokens[0] = AI_MDL_MAGIC_NUMBER_LE_HL2a;
tokens[1] = AI_MDL_MAGIC_NUMBER_LE_HL2b;
tokens[2] = AI_MDL_MAGIC_NUMBER_LE_GS7;
tokens[3] = AI_MDL_MAGIC_NUMBER_LE_GS5b;
tokens[4] = AI_MDL_MAGIC_NUMBER_LE_GS5a;
tokens[5] = AI_MDL_MAGIC_NUMBER_LE_GS4;
tokens[6] = AI_MDL_MAGIC_NUMBER_LE_GS3;
tokens[7] = AI_MDL_MAGIC_NUMBER_LE;
return CheckMagicToken(pIOHandler, pFile, tokens, 8, 0);
}
return false;
bool MDLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const uint32_t tokens[] = {
AI_MDL_MAGIC_NUMBER_LE_HL2a,
AI_MDL_MAGIC_NUMBER_LE_HL2b,
AI_MDL_MAGIC_NUMBER_LE_GS7,
AI_MDL_MAGIC_NUMBER_LE_GS5b,
AI_MDL_MAGIC_NUMBER_LE_GS5a,
AI_MDL_MAGIC_NUMBER_LE_GS4,
AI_MDL_MAGIC_NUMBER_LE_GS3,
AI_MDL_MAGIC_NUMBER_LE
};
return CheckMagicToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -89,14 +89,9 @@ MMDImporter::~MMDImporter() {
// ------------------------------------------------------------------------------------------------
// Returns true, if file is an pmx file.
bool MMDImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler,
bool checkSig) const {
if (!checkSig) {
return SimpleExtensionCheck(pFile, "pmx");
} else {
// Check file Header
static const char * const pTokens[] = { "PMX " };
return SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 1);
}
bool /*checkSig*/) const {
static const char *tokens[] = { "PMX " };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -88,26 +88,12 @@ MS3DImporter::MS3DImporter()
// Destructor, private as well
MS3DImporter::~MS3DImporter()
{}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool MS3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
bool MS3DImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const
{
// first call - simple extension check
const std::string extension = GetExtension(pFile);
if (extension == "ms3d") {
return true;
}
// second call - check for magic identifiers
else if (!extension.length() || checkSig) {
if (!pIOHandler) {
return true;
}
static const char * const tokens[] = {"MS3D000000"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1);
}
return false;
static const char* tokens[] = { "MS3D000000" };
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -82,19 +80,10 @@ NDOImporter::~NDOImporter()
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool NDOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
bool NDOImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const
{
// check file extension
const std::string extension = GetExtension(pFile);
if( extension == "ndo")
return true;
if ((checkSig || !extension.length()) && pIOHandler) {
static const char * const tokens[] = {"nendo"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1,5);
}
return false;
static const char* tokens[] = {"nendo"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,AI_COUNT_OF(tokens),5);
}
// ------------------------------------------------------------------------------------------------

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,

View File

@ -83,19 +83,10 @@ OFFImporter::~OFFImporter()
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool OFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const
bool OFFImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const
{
const std::string extension = GetExtension(pFile);
if (extension == "off")
return true;
else if (!extension.length() || checkSig)
{
if (!pIOHandler)return true;
static const char * const tokens[] = {"off"};
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,1,3);
}
return false;
static const char* tokens[] = { "off" };
return SearchFileHeaderForToken(pIOHandler,pFile,tokens,AI_COUNT_OF(tokens),3);
}
// ------------------------------------------------------------------------------------------------

View File

@ -87,16 +87,10 @@ ObjFileImporter::~ObjFileImporter() {
}
// ------------------------------------------------------------------------------------------------
// Returns true, if file is an obj file.
bool ObjFileImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
if (!checkSig) {
//Check File Extension
return SimpleExtensionCheck(pFile, "obj");
} else {
// Check file Header
static const char *pTokens[] = { "mtllib", "usemtl", "v ", "vt ", "vn ", "o ", "g ", "s ", "f " };
return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, pTokens, 9, 200, false, true);
}
// Returns true if file is an obj file.
bool ObjFileImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const char *tokens[] = { "mtllib", "usemtl", "v ", "vt ", "vn ", "o ", "g ", "s ", "f " };
return BaseImporter::SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens), 200, false, true);
}
// ------------------------------------------------------------------------------------------------

View File

@ -73,14 +73,10 @@ void OgreImporter::SetupProperties(const Importer *pImp) {
m_detectTextureTypeFromFilename = pImp->GetPropertyBool(AI_CONFIG_IMPORT_OGRE_TEXTURETYPE_FROM_FILENAME, false);
}
bool OgreImporter::CanRead(const std::string &pFile, Assimp::IOSystem *pIOHandler, bool checkSig) const {
if (!checkSig) {
return EndsWith(pFile, ".mesh.xml", false) || EndsWith(pFile, ".mesh", false);
}
bool OgreImporter::CanRead(const std::string &pFile, Assimp::IOSystem *pIOHandler, bool /*checkSig*/) const {
if (EndsWith(pFile, ".mesh.xml", false)) {
static const char * const tokens[] = { "<mesh>" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
static const char *tokens[] = { "<mesh>" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
/// @todo Read and validate first header chunk?

View File

@ -290,16 +290,9 @@ OpenGEXImporter::~OpenGEXImporter() {
}
//------------------------------------------------------------------------------------------------
bool OpenGEXImporter::CanRead(const std::string &file, IOSystem *pIOHandler, bool checkSig) const {
bool canRead(false);
if (!checkSig) {
canRead = SimpleExtensionCheck(file, "ogex");
} else {
static const char * const token[] = { "Metric", "GeometryNode", "VertexArray (attrib", "IndexArray" };
canRead = SearchFileHeaderForToken(pIOHandler, file, token, 4);
}
return canRead;
bool OpenGEXImporter::CanRead(const std::string &file, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const char *tokens[] = { "Metric", "GeometryNode", "VertexArray (attrib", "IndexArray" };
return SearchFileHeaderForToken(pIOHandler, file, tokens, AI_COUNT_OF(tokens));
}
//------------------------------------------------------------------------------------------------

View File

@ -100,24 +100,9 @@ PLYImporter::~PLYImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool PLYImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(pFile);
if (extension == "ply") {
return true;
}
if (!extension.length() || checkSig) {
if (!pIOHandler) {
return true;
}
static const char * const tokens[] = {
"ply"
};
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
return false;
bool PLYImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const char *tokens[] = { "ply" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -156,12 +156,11 @@ Q3BSPFileImporter::~Q3BSPFileImporter() {
}
// ------------------------------------------------------------------------------------------------
// Returns true, if the loader can read this.
bool Q3BSPFileImporter::CanRead(const std::string &rFile, IOSystem * /*pIOHandler*/, bool checkSig) const {
// Returns true if the loader can read this.
bool Q3BSPFileImporter::CanRead(const std::string &filename, IOSystem * /*pIOHandler*/, bool checkSig) const {
if (!checkSig) {
return SimpleExtensionCheck(rFile, "pk3", "bsp");
return SimpleExtensionCheck(filename, "pk3", "bsp");
}
return false;
}

View File

@ -84,18 +84,9 @@ Q3DImporter::~Q3DImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool Q3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(pFile);
if (extension == "q3s" || extension == "q3o")
return true;
else if (!extension.length() || checkSig) {
if (!pIOHandler)
return true;
static const char * const tokens[] = { "quick3Do", "quick3Ds" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 2);
}
return false;
bool Q3DImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const char *tokens[] = { "quick3Do", "quick3Ds" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -84,8 +84,8 @@ RAWImporter::~RAWImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool RAWImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
return SimpleExtensionCheck(pFile, "raw");
bool RAWImporter::CanRead(const std::string &filename, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
return SimpleExtensionCheck(filename, "raw");
}
// ------------------------------------------------------------------------------------------------

View File

@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2022, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@ -61,7 +59,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifdef ASSIMP_USE_HUNTER
#include <utf8.h>
#else
//# include "../contrib/ConvertUTF/ConvertUTF.h"
#include "../contrib/utf8cpp/source/utf8.h"
#endif
#include <assimp/importerdesc.h>
@ -217,8 +214,8 @@ SIBImporter::~SIBImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool SIBImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
return SimpleExtensionCheck(pFile, "sib");
bool SIBImporter::CanRead(const std::string &filename, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
return SimpleExtensionCheck(filename, "sib");
}
// ------------------------------------------------------------------------------------------------

View File

@ -81,15 +81,15 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
SMDImporter::SMDImporter()
: configFrameID()
, mBuffer()
, pScene( nullptr )
, iFileSize( 0 )
, iSmallestFrame( INT_MAX )
, dLengthOfAnim( 0.0 )
, bHasUVs(false )
, iLineNumber((unsigned int)-1) {
SMDImporter::SMDImporter() :
configFrameID(),
mBuffer(),
pScene( nullptr ),
iFileSize( 0 ),
iSmallestFrame( INT_MAX ),
dLengthOfAnim( 0.0 ),
bHasUVs(false ),
iLineNumber((unsigned int)-1) {
// empty
}
@ -101,9 +101,8 @@ SMDImporter::~SMDImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool SMDImporter::CanRead( const std::string& pFile, IOSystem* /*pIOHandler*/, bool) const {
// fixme: auto format detection
return SimpleExtensionCheck(pFile,"smd","vta");
bool SMDImporter::CanRead( const std::string& filename, IOSystem* /*pIOHandler*/, bool) const {
return SimpleExtensionCheck(filename, "smd", "vta");
}
// ------------------------------------------------------------------------------------------------

View File

@ -140,22 +140,9 @@ STLImporter::~STLImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool STLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
const std::string extension = GetExtension(pFile);
if (extension == "stl") {
return true;
}
if (!extension.length() || checkSig) {
if (!pIOHandler) {
return true;
}
static const char * const tokens[] = { "STL", "solid" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 2);
}
return false;
bool STLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const char *tokens[] = { "STL", "solid" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -81,27 +81,9 @@ TerragenImporter::~TerragenImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool TerragenImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
// check file extension
std::string extension = GetExtension(pFile);
if (extension == "ter")
return true;
if (!extension.length() || checkSig) {
/* If CanRead() is called in order to check whether we
* support a specific file extension in general pIOHandler
* might be nullptr and it's our duty to return true here.
*/
if (!pIOHandler) {
return true;
}
static const char * const tokens[] = { "terragen" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 1);
}
return false;
bool TerragenImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const char *tokens[] = { "terragen" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -168,16 +168,20 @@ static const aiImporterDesc desc = {
// ------------------------------------------------------------------------------------------------
// Constructor to be privately used by Importer
UnrealImporter::UnrealImporter() :
mConfigFrameID(0), mConfigHandleFlags(true) {}
mConfigFrameID(0), mConfigHandleFlags(true) {
// empty
}
// ------------------------------------------------------------------------------------------------
// Destructor, private as well
UnrealImporter::~UnrealImporter() {}
UnrealImporter::~UnrealImporter() {
// empty
}
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool UnrealImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
return SimpleExtensionCheck(pFile, "3d", "uc");
bool UnrealImporter::CanRead(const std::string & filename, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
return SimpleExtensionCheck(filename, "3d", "uc");
}
// ------------------------------------------------------------------------------------------------

View File

@ -88,17 +88,9 @@ XFileImporter::~XFileImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool XFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool checkSig) const {
std::string extension = GetExtension(pFile);
if(extension == "x") {
return true;
}
if (!extension.length() || checkSig) {
uint32_t token[1];
token[0] = AI_MAKE_MAGIC("xof ");
return CheckMagicToken(pIOHandler,pFile,token,1,0);
}
return false;
bool XFileImporter::CanRead( const std::string& pFile, IOSystem* pIOHandler, bool /*checkSig*/) const {
static const uint32_t token[] = { AI_MAKE_MAGIC("xof ") };
return CheckMagicToken(pIOHandler,pFile,token,AI_COUNT_OF(token));
}
// ------------------------------------------------------------------------------------------------

View File

@ -104,25 +104,9 @@ XGLImporter::~XGLImporter() {
// ------------------------------------------------------------------------------------------------
// Returns whether the class can handle the format of the given file.
bool XGLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig) const {
/* NOTE: A simple check for the file extension is not enough
* here. XGL and ZGL are ok, but xml is too generic
* and might be collada as well. So open the file and
* look for typical signal tokens.
*/
const std::string extension = GetExtension(pFile);
if (extension == "xgl" || extension == "zgl") {
return true;
}
if (extension == "xml" || checkSig) {
ai_assert(pIOHandler != nullptr);
static const char * const tokens[] = { "<world>", "<World>", "<WORLD>" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, 3);
}
return false;
bool XGLImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const char *tokens[] = { "<world>", "<World>", "<WORLD>" };
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
}
// ------------------------------------------------------------------------------------------------

View File

@ -93,16 +93,9 @@ const aiImporterDesc *glTFImporter::GetInfo() const {
}
bool glTFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /* checkSig */) const {
const std::string &extension = GetExtension(pFile);
if (extension != "gltf" && extension != "glb") {
return false;
}
if (pIOHandler) {
glTF::Asset asset(pIOHandler);
try {
asset.Load(pFile, extension == "glb");
asset.Load(pFile, GetExtension(pFile) == "glb");
std::string version = asset.asset.version;
return !version.empty() && version[0] == '1';
} catch (...) {
@ -110,9 +103,6 @@ bool glTFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool
}
}
return false;
}
inline void SetMaterialColorProperty(std::vector<int> &embeddedTexIdxs, Asset & /*r*/, glTF::TexProperty prop, aiMaterial *mat,
aiTextureType texType, const char *pKey, unsigned int type, unsigned int idx) {
if (prop.texture) {

View File

@ -98,7 +98,7 @@ static const aiImporterDesc desc = {
glTF2Importer::glTF2Importer() :
BaseImporter(),
meshOffsets(),
embeddedTexIdxs(),
mEmbeddedTexIdxs(),
mScene(nullptr) {
// empty
}
@ -111,21 +111,21 @@ const aiImporterDesc *glTF2Importer::GetInfo() const {
return &desc;
}
bool glTF2Importer::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool checkSig ) const {
const std::string &extension = GetExtension(pFile);
if (!checkSig && (extension != "gltf") && (extension != "glb"))
bool glTF2Importer::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig ) const {
const std::string extension = GetExtension(filename);
if (!checkSig && (extension != "gltf") && (extension != "glb")) {
return false;
}
if (pIOHandler) {
glTF2::Asset asset(pIOHandler);
return asset.CanRead(pFile, extension == "glb");
return asset.CanRead(filename, extension == "glb");
}
return false;
}
static aiTextureMapMode ConvertWrappingMode(SamplerWrap gltfWrapMode) {
static inline aiTextureMapMode ConvertWrappingMode(SamplerWrap gltfWrapMode) {
switch (gltfWrapMode) {
case SamplerWrap::Mirrored_Repeat:
return aiTextureMapMode_Mirror;
@ -140,21 +140,21 @@ static aiTextureMapMode ConvertWrappingMode(SamplerWrap gltfWrapMode) {
}
}
inline void SetMaterialColorProperty(Asset & /*r*/, vec4 &prop, aiMaterial *mat,
static inline void SetMaterialColorProperty(Asset & /*r*/, vec4 &prop, aiMaterial *mat,
const char *pKey, unsigned int type, unsigned int idx) {
aiColor4D col;
CopyValue(prop, col);
mat->AddProperty(&col, 1, pKey, type, idx);
}
inline void SetMaterialColorProperty(Asset & /*r*/, vec3 &prop, aiMaterial *mat,
static inline void SetMaterialColorProperty(Asset & /*r*/, vec3 &prop, aiMaterial *mat,
const char *pKey, unsigned int type, unsigned int idx) {
aiColor4D col;
glTFCommon::CopyValue(prop, col);
mat->AddProperty(&col, 1, pKey, type, idx);
}
inline void SetMaterialTextureProperty(std::vector<int> &embeddedTexIdxs, Asset & /*r*/,
static void SetMaterialTextureProperty(std::vector<int> &embeddedTexIdxs, Asset & /*r*/,
glTF2::TextureInfo prop, aiMaterial *mat, aiTextureType texType,
unsigned int texSlot = 0) {
if (prop.texture && prop.texture->source) {
@ -371,10 +371,10 @@ void glTF2Importer::ImportMaterials(Asset &r) {
mScene->mNumMaterials = numImportedMaterials + 1;
mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials];
std::fill(mScene->mMaterials, mScene->mMaterials + mScene->mNumMaterials, nullptr);
mScene->mMaterials[numImportedMaterials] = ImportMaterial(embeddedTexIdxs, r, defaultMaterial);
mScene->mMaterials[numImportedMaterials] = ImportMaterial(mEmbeddedTexIdxs, r, defaultMaterial);
for (unsigned int i = 0; i < numImportedMaterials; ++i) {
mScene->mMaterials[i] = ImportMaterial(embeddedTexIdxs, r, r.materials[i]);
mScene->mMaterials[i] = ImportMaterial(mEmbeddedTexIdxs, r, r.materials[i]);
}
}
@ -802,8 +802,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) {
if (actualNumFaces < nFaces) {
ASSIMP_LOG_WARN("Some faces had out-of-range indices. Those faces were dropped.");
}
if (actualNumFaces == 0)
{
if (actualNumFaces == 0) {
throw DeadlyImportError("Mesh \"", aim->mName.C_Str(), "\" has no faces");
}
aim->mNumFaces = actualNumFaces;
@ -843,7 +842,6 @@ void glTF2Importer::ImportCameras(glTF2::Asset &r) {
aicam->mLookAt = aiVector3D(0.f, 0.f, -1.f);
if (cam.type == Camera::Perspective) {
aicam->mAspect = cam.cameraProperties.perspective.aspectRatio;
aicam->mHorizontalFOV = cam.cameraProperties.perspective.yfov * ((aicam->mAspect == 0.f) ? 1.f : aicam->mAspect);
aicam->mClipPlaneFar = cam.cameraProperties.perspective.zfar;
@ -862,8 +860,9 @@ void glTF2Importer::ImportCameras(glTF2::Asset &r) {
}
void glTF2Importer::ImportLights(glTF2::Asset &r) {
if (!r.lights.Size())
if (!r.lights.Size()) {
return;
}
const unsigned int numLights = r.lights.Size();
ASSIMP_LOG_DEBUG("Importing ", numLights, " lights");
@ -1167,8 +1166,7 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
if (!ainode->mMetaData) {
ainode->mMetaData = aiMetadata::Alloc(1);
ainode->mMetaData->Set(0, "PBR_LightRange", node.light->range.value);
}
else {
} else {
ainode->mMetaData->Add("PBR_LightRange", node.light->range.value);
}
}
@ -1509,16 +1507,20 @@ void glTF2Importer::ImportAnimations(glTF2::Asset &r) {
}
}
void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) {
embeddedTexIdxs.resize(r.images.Size(), -1);
int numEmbeddedTexs = 0;
static unsigned int countEmbeddedTextures(glTF2::Asset &r) {
unsigned int numEmbeddedTexs = 0;
for (size_t i = 0; i < r.images.Size(); ++i) {
if (r.images[i].HasData()) {
numEmbeddedTexs += 1;
}
}
return numEmbeddedTexs;
}
void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) {
mEmbeddedTexIdxs.resize(r.images.Size(), -1);
const unsigned int numEmbeddedTexs = countEmbeddedTextures(r);
if (numEmbeddedTexs == 0) {
return;
}
@ -1536,7 +1538,7 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) {
}
int idx = mScene->mNumTextures++;
embeddedTexIdxs[i] = idx;
mEmbeddedTexIdxs[i] = idx;
aiTexture *tex = mScene->mTextures[idx] = new aiTexture();
@ -1597,7 +1599,7 @@ void glTF2Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IO
// clean all member arrays
meshOffsets.clear();
embeddedTexIdxs.clear();
mEmbeddedTexIdxs.clear();
this->mScene = pScene;

View File

@ -79,7 +79,7 @@ private:
private:
std::vector<unsigned int> meshOffsets;
std::vector<int> embeddedTexIdxs;
std::vector<int> mEmbeddedTexIdxs;
aiScene *mScene;
/// An instance of rapidjson::IRemoteSchemaDocumentProvider

View File

@ -376,6 +376,12 @@ ADD_ASSIMP_IMPORTER( IRRMESH
AssetLib/Irr/IRRShared.h
)
ADD_ASSIMP_IMPORTER( IQM
AssetLib/IQM/IQMImporter.cpp
AssetLib/IQM/iqm.h
AssetLib/IQM/IQMImporter.h
)
ADD_ASSIMP_IMPORTER( IRR
AssetLib/Irr/IRRLoader.cpp
AssetLib/Irr/IRRLoader.h

View File

@ -156,8 +156,8 @@ void BaseImporter::GetExtensionList(std::set<std::string> &extensions) {
// ------------------------------------------------------------------------------------------------
/*static*/ bool BaseImporter::SearchFileHeaderForToken(IOSystem *pIOHandler,
const std::string &pFile,
const char * const *tokens,
unsigned int numTokens,
const char **tokens,
std::size_t numTokens,
unsigned int searchBytes /* = 200 */,
bool tokensSol /* false */,
bool noAlphaBeforeTokens /* false */) {
@ -268,10 +268,11 @@ std::string BaseImporter::GetExtension(const std::string &file) {
return ret;
}
// ------------------------------------------------------------------------------------------------
// Check for magic bytes at the beginning of the file.
/* static */ bool BaseImporter::CheckMagicToken(IOSystem *pIOHandler, const std::string &pFile,
const void *_magic, unsigned int num, unsigned int offset, unsigned int size) {
const void *_magic, std::size_t num, unsigned int offset, unsigned int size) {
ai_assert(size <= 16);
ai_assert(_magic);

View File

@ -388,15 +388,16 @@ void DefaultLogger::WriteToStreams(const char *message, ErrorSeverity ErrorSev)
ai_assert(nullptr != message);
// Check whether this is a repeated message
if (!::strncmp(message, lastMsg, lastLen - 1)) {
auto thisLen = ::strlen(message);
if (thisLen == lastLen - 1 && !::strncmp(message, lastMsg, lastLen - 1)) {
if (!noRepeatMsg) {
noRepeatMsg = true;
message = "Skipping one or more lines with the same contents\n";
} else
}
return;
} else {
// append a new-line character to the message to be printed
lastLen = ::strlen(message);
lastLen = thisLen;
::memcpy(lastMsg, message, lastLen + 1);
::strcat(lastMsg + lastLen, "\n");

View File

@ -617,22 +617,65 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) {
profiler->BeginRegion("total");
}
// Find an worker class which can handle the file
BaseImporter* imp = nullptr;
// Find an worker class which can handle the file extension.
// Multiple importers may be able to handle the same extension (.xml!); gather them all.
SetPropertyInteger("importerIndex", -1);
struct ImporterAndIndex {
BaseImporter * importer;
unsigned int index;
};
std::vector<ImporterAndIndex> possibleImporters;
for (unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, false)) {
imp = pimpl->mImporter[a];
SetPropertyInteger("importerIndex", a);
// Every importer has a list of supported extensions.
std::set<std::string> extensions;
pimpl->mImporter[a]->GetExtensionList(extensions);
// CAUTION: Do not just search for the extension!
// GetExtension() returns the part after the *last* dot, but some extensions have dots
// inside them, e.g. ogre.mesh.xml. Compare the entire end of the string.
for (std::set<std::string>::const_iterator it = extensions.cbegin(); it != extensions.cend(); ++it) {
// Yay for C++<20 not having std::string::ends_with()
std::string extension = "." + *it;
if (extension.length() <= pFile.length()) {
// Possible optimization: Fetch the lowercase filename!
if (0 == ASSIMP_stricmp(pFile.c_str() + pFile.length() - extension.length(), extension.c_str())) {
ImporterAndIndex candidate = { pimpl->mImporter[a], a };
possibleImporters.push_back(candidate);
break;
}
}
}
}
// If just one importer supports this extension, pick it and close the case.
BaseImporter* imp = nullptr;
if (1 == possibleImporters.size()) {
imp = possibleImporters[0].importer;
SetPropertyInteger("importerIndex", possibleImporters[0].index);
}
// If multiple importers claim this file extension, ask them to look at the actual file data to decide.
// This can happen e.g. with XML (COLLADA vs. Irrlicht).
else {
for (std::vector<ImporterAndIndex>::const_iterator it = possibleImporters.begin(); it < possibleImporters.end(); ++it) {
BaseImporter & importer = *it->importer;
ASSIMP_LOG_INFO("Found a possible importer: " + std::string(importer.GetInfo()->mName) + "; trying signature-based detection");
if (importer.CanRead( pFile, pimpl->mIOHandler, true)) {
imp = &importer;
SetPropertyInteger("importerIndex", it->index);
break;
}
}
}
if (!imp) {
// not so bad yet ... try format auto detection.
const std::string::size_type s = pFile.find_last_of('.');
if (s != std::string::npos) {
ASSIMP_LOG_INFO("File extension not known, trying signature-based detection");
for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
if( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, true)) {
@ -641,7 +684,6 @@ const aiScene* Importer::ReadFile( const char* _pFile, unsigned int pFlags) {
break;
}
}
}
// Put a proper error message if no suitable importer was found
if( !imp) {
pimpl->mErrorString = "No suitable reader found for the file format of file \"" + pFile + "\".";

View File

@ -202,6 +202,9 @@ corresponding preprocessor flag to selectively disable formats.
#ifndef ASSIMP_BUILD_NO_M3D_IMPORTER
#include "AssetLib/M3D/M3DImporter.h"
#endif
#ifndef ASSIMP_BUILD_NO_IQM_IMPORTER
#include "AssetLib/IQM/IQMImporter.h"
#endif
namespace Assimp {
@ -370,6 +373,9 @@ void GetImporterInstanceList(std::vector<BaseImporter *> &out) {
#endif
#ifndef ASSIMP_BUILD_NO_MMD_IMPORTER
out.push_back(new MMDImporter());
#endif
#ifndef ASSIMP_BUILD_NO_IQM_IMPORTER
out.push_back(new IQMImporter());
#endif
//#ifndef ASSIMP_BUILD_NO_STEP_IMPORTER
// out.push_back(new StepFile::StepFileImporter());

View File

@ -95,20 +95,15 @@ public:
// -------------------------------------------------------------------
/** Returns whether the class can handle the format of the given file.
*
* The implementation should be as quick as possible. A check for
* the file extension is enough. If no suitable loader is found with
* this strategy, CanRead() is called again, the 'checkSig' parameter
* set to true this time. Now the implementation is expected to
* perform a full check of the file structure, possibly searching the
* first bytes of the file for magic identifiers or keywords.
* The implementation is expected to perform a full check of the file
* structure, possibly searching the first bytes of the file for magic
* identifiers or keywords.
*
* @param pFile Path and file name of the file to be examined.
* @param pIOHandler The IO handler to use for accessing any file.
* @param checkSig Set to true if this method is called a second time.
* This time, the implementation may take more time to examine the
* contents of the file to be loaded for magic bytes, keywords, etc
* to be able to load files with unknown/not existent file extensions.
* @return true if the class can read this file, false if not.
* @param checkSig Legacy; do not use.
* @return true if the class can read this file, false if not or if
* unsure.
*/
virtual bool CanRead(
const std::string &pFile,
@ -259,8 +254,8 @@ public: // static utilities
static bool SearchFileHeaderForToken(
IOSystem *pIOSystem,
const std::string &file,
const char * const *tokens,
unsigned int numTokens,
const char **tokens,
std::size_t numTokens,
unsigned int searchBytes = 200,
bool tokensSol = false,
bool noAlphaBeforeTokens = false);
@ -305,7 +300,7 @@ public: // static utilities
IOSystem *pIOHandler,
const std::string &pFile,
const void *magic,
unsigned int num,
std::size_t num,
unsigned int offset = 0,
unsigned int size = 4);

View File

@ -331,4 +331,6 @@ static const ai_real ai_epsilon = (ai_real)0.00001;
#define AI_DEBUG_INVALIDATE_PTR(x)
#endif
#define AI_COUNT_OF(X) (sizeof(X) / sizeof((X)[0]))
#endif // !! AI_DEFINES_H_INC

Binary file not shown.

After

Width:  |  Height:  |  Size: 361 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.