Merge branch 'master' into respect-cmake-output-variables
commit
6cc469a5ae
|
@ -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]);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -90,24 +90,12 @@ 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;
|
||||
}
|
||||
if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) {
|
||||
return false;
|
||||
}
|
||||
D3MFOpcPackage opcPackage(pIOHandler, filename);
|
||||
return opcPackage.validate();
|
||||
bool D3MFImporter::CanRead(const std::string &filename, IOSystem *pIOHandler, bool /*checkSig*/) const {
|
||||
if (!ZipArchiveIOSystem::isZipArchive(pIOHandler, filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
D3MF::D3MFOpcPackage opcPackage(pIOHandler, filename);
|
||||
return opcPackage.validate();
|
||||
}
|
||||
|
||||
void D3MFImporter::SetupProperties(const Importer*) {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -81,7 +81,7 @@ static const aiImporterDesc desc = {
|
|||
|
||||
//#define DEBUG_B3D
|
||||
|
||||
template <typename T>
|
||||
template<typename T>
|
||||
void DeleteAllBarePointers(std::vector<T> &x) {
|
||||
for (auto p : x) {
|
||||
delete p;
|
||||
|
@ -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;
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
bool BlenderImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool /*checkSig*/) const {
|
||||
// note: this won't catch compressed files
|
||||
static const char *tokens[] = { "<BLENDER", "blender" };
|
||||
|
||||
if ((!extension.length() || checkSig) && pIOHandler) {
|
||||
// note: this won't catch compressed files
|
||||
return SearchFileHeaderForToken(pIOHandler, pFile, TokensForSearch, 1);
|
||||
}
|
||||
|
||||
return false;
|
||||
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -106,14 +106,25 @@ 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;
|
||||
} else if ((!extension.length() || checkSig) && pIOHandler) {
|
||||
// TODO
|
||||
}
|
||||
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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 {
|
||||
// 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();
|
||||
}
|
||||
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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -331,7 +331,16 @@ void ColladaParser::ReadAssetInfo(XmlNode &node) {
|
|||
const std::string ¤tName = 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,20 +2251,26 @@ 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");
|
||||
// read ID of the geometry subgroup and the target material
|
||||
std::string group;
|
||||
XmlParser::getStdStrAttribute(instanceMatNode, "symbol", group);
|
||||
XmlParser::getStdStrAttribute(instanceMatNode, "target", url);
|
||||
const char *urlMat = url.c_str();
|
||||
Collada::SemanticMappingTable s;
|
||||
if (urlMat[0] == '#')
|
||||
urlMat++;
|
||||
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);
|
||||
XmlParser::getStdStrAttribute(instanceMatNode, "target", url);
|
||||
const char *urlMat = url.c_str();
|
||||
Collada::SemanticMappingTable s;
|
||||
if (urlMat[0] == '#')
|
||||
urlMat++;
|
||||
|
||||
s.mMatName = urlMat;
|
||||
// store the association
|
||||
instance.mMaterials[group] = s;
|
||||
ReadMaterialVertexInputBinding(instanceMatNode, s);
|
||||
s.mMatName = urlMat;
|
||||
// store the association
|
||||
instance.mMaterials[group] = s;
|
||||
ReadMaterialVertexInputBinding(instanceMatNode, s);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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) {
|
||||
// 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;
|
||||
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 *tokens[] = { "fbx" };
|
||||
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -622,31 +661,33 @@ void ProcessExtrudedArea(const Schema_2x3::IfcExtrudedAreaSolid& solid, const Te
|
|||
}
|
||||
}
|
||||
|
||||
if( openings ) {
|
||||
if(openings) {
|
||||
for(TempOpening& opening : *conv.apply_openings) {
|
||||
if( !opening.wallPoints.empty() ) {
|
||||
IFCImporter::LogError("failed to generate all window caps");
|
||||
if(!opening.wallPoints.empty()) {
|
||||
std::stringstream msg;
|
||||
msg << "failed to generate all window caps on ID " << (int)solid.GetID();
|
||||
IFCImporter::LogError(msg.str().c_str());
|
||||
}
|
||||
opening.wallPoints.clear();
|
||||
}
|
||||
}
|
||||
|
||||
size_t sides_with_v_openings = 0;
|
||||
if( has_area ) {
|
||||
if(has_area) {
|
||||
|
||||
for( size_t n = 0; n < 2; ++n ) {
|
||||
if( n > 0 ) {
|
||||
for( size_t i = 0; i < in.size(); ++i )
|
||||
for(size_t n = 0; n < 2; ++n) {
|
||||
if(n > 0) {
|
||||
for(size_t i = 0; i < in.size(); ++i)
|
||||
out.push_back(in[i] + dir);
|
||||
}
|
||||
else {
|
||||
for( size_t i = in.size(); i--; )
|
||||
for(size_t i = in.size(); i--; )
|
||||
out.push_back(in[i]);
|
||||
}
|
||||
|
||||
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(openings && in.size() > 2) {
|
||||
if(GenerateOpenings(*conv.apply_openings,temp,true,true,dir)) {
|
||||
++sides_with_v_openings;
|
||||
}
|
||||
|
||||
|
@ -656,8 +697,10 @@ 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");
|
||||
if (openings && (sides_with_openings == 1 || sides_with_v_openings == 2)) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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) {
|
||||
// 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;
|
||||
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 *tokens[] = { "ISO-10303-21" };
|
||||
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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,61 +1780,41 @@ 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;
|
||||
}
|
||||
for(const TempOpening& t : openings) {
|
||||
auto contours = GetContoursInPlane(t.profileMesh,m,nor,coord,t.extrusionDir,wall_extrusion,first);
|
||||
|
||||
const std::vector<IfcVector3>& va = t.profileMesh->mVerts;
|
||||
if(va.size() <= 2) {
|
||||
continue;
|
||||
}
|
||||
for(auto& contour : contours) {
|
||||
// scale to clipping space
|
||||
ClipperLib::Polygon hole;
|
||||
for(IfcVector2& pip : contour) {
|
||||
pip.x = (pip.x - vmin.x) / vmax.x;
|
||||
pip.y = (pip.y - vmin.y) / vmax.y;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
hole.push_back(ClipperLib::IntPoint(to_int64(pip.x),to_int64(pip.y)));
|
||||
}
|
||||
|
||||
// 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));
|
||||
if(!ClipperLib::Orientation(hole)) {
|
||||
std::reverse(hole.begin(),hole.end());
|
||||
// assert(ClipperLib::Orientation(hole));
|
||||
}
|
||||
|
||||
/*ClipperLib::Polygons pol_temp(1), pol_temp2(1);
|
||||
pol_temp[0] = hole;
|
||||
|
||||
ClipperLib::OffsetPolygons(pol_temp,pol_temp2,5.0);
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
ClipperLib::Polygon hole;
|
||||
for(IfcVector2& pip : contour) {
|
||||
pip.x = (pip.x - vmin.x) / vmax.x;
|
||||
pip.y = (pip.y - vmin.y) / vmax.y;
|
||||
|
||||
hole.push_back(ClipperLib::IntPoint( to_int64(pip.x), to_int64(pip.y) ));
|
||||
}
|
||||
|
||||
if (!ClipperLib::Orientation(hole)) {
|
||||
std::reverse(hole.begin(), hole.end());
|
||||
// assert(ClipperLib::Orientation(hole));
|
||||
}
|
||||
|
||||
/*ClipperLib::Polygons pol_temp(1), pol_temp2(1);
|
||||
pol_temp[0] = hole;
|
||||
|
||||
ClipperLib::OffsetPolygons(pol_temp,pol_temp2,5.0);
|
||||
hole = pol_temp2[0];*/
|
||||
|
||||
clipper_holes.AddPolygon(hole,ClipperLib::ptSubject);
|
||||
}
|
||||
|
||||
clipper_holes.Execute(ClipperLib::ctUnion,holes_union,
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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;
|
||||
* 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.
|
||||
*/
|
||||
static const char *tokens[] = { "irrmesh" };
|
||||
return SearchFileHeaderForToken(pIOHandler, pFile, tokens, AI_COUNT_OF(tokens));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -111,34 +111,19 @@ 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);
|
||||
*/
|
||||
std::unique_ptr<IOStream> pStream(pIOHandler->Open(pFile, "rb"));
|
||||
unsigned char data[4];
|
||||
if (!pStream || 4 != pStream->Read(data, 1, 4)) {
|
||||
return false;
|
||||
}
|
||||
return !memcmp(data, "3DMO", 4) /* bin */
|
||||
|| !memcmp(data, "3dmo", 4) /* ASCII */
|
||||
;
|
||||
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 (4 != pStream->Read(data, 1, 4)) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
return !memcmp(data, "3DMO", 4) /* bin */
|
||||
#ifdef M3D_ASCII
|
||||
|| !memcmp(data, "3dmo", 4) /* ASCII */
|
||||
#endif
|
||||
;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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,
|
||||
|
@ -83,7 +81,7 @@ NFFImporter::~NFFImporter() {}
|
|||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// Returns whether the class can handle the format of the given file.
|
||||
bool NFFImporter::CanRead(const std::string &pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
|
||||
bool NFFImporter::CanRead(const std::string & pFile, IOSystem * /*pIOHandler*/, bool /*checkSig*/) const {
|
||||
return SimpleExtensionCheck(pFile, "nff", "enff");
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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?
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -74,7 +74,7 @@ namespace Unreal {
|
|||
3 = Masked two-sided
|
||||
4 = Modulation blended two-sided
|
||||
8 = Placeholder triangle for weapon positioning (invisible)
|
||||
*/
|
||||
*/
|
||||
enum MeshFlags {
|
||||
MF_NORMAL_OS = 0,
|
||||
MF_NORMAL_TS = 1,
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -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));
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
|
|
@ -93,24 +93,14 @@ 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") {
|
||||
glTF::Asset asset(pIOHandler);
|
||||
try {
|
||||
asset.Load(pFile, GetExtension(pFile) == "glb");
|
||||
std::string version = asset.asset.version;
|
||||
return !version.empty() && version[0] == '1';
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (pIOHandler) {
|
||||
glTF::Asset asset(pIOHandler);
|
||||
try {
|
||||
asset.Load(pFile, extension == "glb");
|
||||
std::string version = asset.asset.version;
|
||||
return !version.empty() && version[0] == '1';
|
||||
} catch (...) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
inline void SetMaterialColorProperty(std::vector<int> &embeddedTexIdxs, Asset & /*r*/, glTF::TexProperty prop, aiMaterial *mat,
|
||||
|
|
|
@ -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);
|
||||
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 (!checkSig && (extension != "gltf") && (extension != "glb"))
|
||||
return false;
|
||||
|
||||
if (pIOHandler) {
|
||||
glTF2::Asset asset(pIOHandler);
|
||||
return asset.CanRead(pFile, extension == "glb");
|
||||
}
|
||||
if (pIOHandler) {
|
||||
glTF2::Asset asset(pIOHandler);
|
||||
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");
|
||||
|
@ -1125,8 +1124,8 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector<unsigned int> &
|
|||
bone->mNumWeights = static_cast<uint32_t>(weights.size());
|
||||
|
||||
if (bone->mNumWeights > 0) {
|
||||
bone->mWeights = new aiVertexWeight[bone->mNumWeights];
|
||||
memcpy(bone->mWeights, weights.data(), bone->mNumWeights * sizeof(aiVertexWeight));
|
||||
bone->mWeights = new aiVertexWeight[bone->mNumWeights];
|
||||
memcpy(bone->mWeights, weights.data(), bone->mNumWeights * sizeof(aiVertexWeight));
|
||||
} else {
|
||||
// Assimp expects all bones to have at least 1 weight.
|
||||
bone->mWeights = new aiVertexWeight[1];
|
||||
|
@ -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;
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
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");
|
||||
|
||||
|
|
|
@ -617,29 +617,71 @@ 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);
|
||||
for( unsigned int a = 0; a < pimpl->mImporter.size(); a++) {
|
||||
struct ImporterAndIndex {
|
||||
BaseImporter * importer;
|
||||
unsigned int index;
|
||||
};
|
||||
std::vector<ImporterAndIndex> possibleImporters;
|
||||
for (unsigned int a = 0; a < pimpl->mImporter.size(); 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( pimpl->mImporter[a]->CanRead( pFile, pimpl->mIOHandler, false)) {
|
||||
imp = pimpl->mImporter[a];
|
||||
SetPropertyInteger("importerIndex", a);
|
||||
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)) {
|
||||
imp = pimpl->mImporter[a];
|
||||
SetPropertyInteger("importerIndex", a);
|
||||
break;
|
||||
}
|
||||
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)) {
|
||||
imp = pimpl->mImporter[a];
|
||||
SetPropertyInteger("importerIndex", a);
|
||||
break;
|
||||
}
|
||||
}
|
||||
// Put a proper error message if no suitable importer was found
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
Loading…
Reference in New Issue