Merge branch 'master' into fix/collada_parser_sid

pull/4538/head
Kim Kulling 2022-07-29 19:17:43 +02:00 committed by GitHub
commit 4f6640278a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 775 additions and 444 deletions

6
.github/dependabot.yml vendored 100644
View File

@ -0,0 +1,6 @@
version: 2
updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
interval: "weekly"

View File

@ -43,7 +43,7 @@ jobs:
toolchain: ninja-vs-win64-cxx17 toolchain: ninja-vs-win64-cxx17
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: lukka/get-cmake@latest - uses: lukka/get-cmake@latest
@ -64,21 +64,21 @@ jobs:
- name: Checkout Hunter toolchains - name: Checkout Hunter toolchains
if: endsWith(matrix.name, 'hunter') if: endsWith(matrix.name, 'hunter')
uses: actions/checkout@v2 uses: actions/checkout@v3
with: with:
repository: cpp-pm/polly repository: cpp-pm/polly
path: cmake/polly path: cmake/polly
- name: Remove contrib directory for Hunter builds - name: Remove contrib directory for Hunter builds
if: contains(matrix.name, 'hunter') if: contains(matrix.name, 'hunter')
uses: JesseTG/rm@v1.0.2 uses: JesseTG/rm@v1.0.3
with: with:
path: contrib path: contrib
- name: Cache DX SDK - name: Cache DX SDK
id: dxcache id: dxcache
if: contains(matrix.name, 'windows') if: contains(matrix.name, 'windows')
uses: actions/cache@v2 uses: actions/cache@v3
with: with:
path: '${{ github.workspace }}/DX_SDK' path: '${{ github.workspace }}/DX_SDK'
key: ${{ runner.os }}-DX_SDK key: ${{ runner.os }}-DX_SDK
@ -122,7 +122,7 @@ jobs:
run: cd build/bin && ./unit ${{ steps.hunter_extra_test_args.outputs.args }} run: cd build/bin && ./unit ${{ steps.hunter_extra_test_args.outputs.args }}
shell: bash shell: bash
- uses: actions/upload-artifact@v2 - uses: actions/upload-artifact@v3
if: matrix.name == 'windows-msvc' if: matrix.name == 'windows-msvc'
with: with:
name: 'assimp-bins-${{ matrix.name }}-${{ github.sha }}' name: 'assimp-bins-${{ matrix.name }}-${{ github.sha }}'

View File

@ -11,7 +11,7 @@ jobs:
name: adress-sanitizer name: adress-sanitizer
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: lukka/get-cmake@latest - uses: lukka/get-cmake@latest
- uses: lukka/set-shell-env@v1 - uses: lukka/set-shell-env@v1
with: with:
@ -35,7 +35,7 @@ jobs:
name: undefined-behavior-sanitizer name: undefined-behavior-sanitizer
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v2 - uses: actions/checkout@v3
- uses: lukka/get-cmake@latest - uses: lukka/get-cmake@latest
- uses: lukka/set-shell-env@v1 - uses: lukka/set-shell-env@v1
with: with:

View File

@ -14,7 +14,8 @@ The assimp port in vcpkg is kept up to date by Microsoft team members and commun
## Install on Ubuntu ## Install on Ubuntu
You can install the Asset-Importer-Lib via apt: You can install the Asset-Importer-Lib via apt:
``` ```
sudo apt-get install assimp sudo apt-get update
sudo apt-get install libassimp-dev
``` ```
## Install pyassimp ## Install pyassimp

View File

@ -90,7 +90,7 @@ OPTION( ASSIMP_BUILD_ZLIB
) )
OPTION( ASSIMP_BUILD_ASSIMP_TOOLS OPTION( ASSIMP_BUILD_ASSIMP_TOOLS
"If the supplementary tools for Assimp are built in addition to the library." "If the supplementary tools for Assimp are built in addition to the library."
ON OFF
) )
OPTION ( ASSIMP_BUILD_SAMPLES OPTION ( ASSIMP_BUILD_SAMPLES
"If the official samples are built as well (needs Glut)." "If the official samples are built as well (needs Glut)."

View File

@ -74,6 +74,8 @@ namespace XmlTag {
const char* const pid = "pid"; const char* const pid = "pid";
const char* const pindex = "pindex"; const char* const pindex = "pindex";
const char* const p1 = "p1"; const char* const p1 = "p1";
const char *const p2 = "p2";
const char *const p3 = "p3";
const char* const name = "name"; const char* const name = "name";
const char* const type = "type"; const char* const type = "type";
const char* const build = "build"; const char* const build = "build";

View File

@ -186,6 +186,9 @@ D3MFOpcPackage::D3MFOpcPackage(IOSystem *pIOHandler, const std::string &rFile) :
D3MFOpcPackage::~D3MFOpcPackage() { D3MFOpcPackage::~D3MFOpcPackage() {
mZipArchive->Close(mRootStream); mZipArchive->Close(mRootStream);
delete mZipArchive; delete mZipArchive;
for (auto tex : mEmbeddedTextures) {
delete tex;
}
} }
IOStream *D3MFOpcPackage::RootStream() const { IOStream *D3MFOpcPackage::RootStream() const {

View File

@ -64,7 +64,7 @@ bool validateColorString(const char *color) {
return true; return true;
} }
aiFace ReadTriangle(XmlNode &node) { aiFace ReadTriangle(XmlNode &node, int &texId0, int &texId1, int &texId2) {
aiFace face; aiFace face;
face.mNumIndices = 3; face.mNumIndices = 3;
@ -73,6 +73,11 @@ aiFace ReadTriangle(XmlNode &node) {
face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v2).as_string())); face.mIndices[1] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v2).as_string()));
face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string())); face.mIndices[2] = static_cast<unsigned int>(std::atoi(node.attribute(XmlTag::v3).as_string()));
texId0 = texId1 = texId2 = -1;
XmlParser::getIntAttribute(node, XmlTag::p1, texId0);
XmlParser::getIntAttribute(node, XmlTag::p2, texId1);
XmlParser::getIntAttribute(node, XmlTag::p3, texId2);
return face; return face;
} }
@ -412,6 +417,9 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid); bool hasPid = getNodeAttribute(currentNode, D3MF::XmlTag::pid, pid);
bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1); bool hasP1 = getNodeAttribute(currentNode, D3MF::XmlTag::p1, p1);
int texId[3];
Texture2DGroup *group = nullptr;
aiFace face = ReadTriangle(currentNode, texId[0], texId[1], texId[2]);
if (hasPid && hasP1) { if (hasPid && hasP1) {
auto it = mResourcesDictionnary.find(pid); auto it = mResourcesDictionnary.find(pid);
if (it != mResourcesDictionnary.end()) { if (it != mResourcesDictionnary.end()) {
@ -420,23 +428,34 @@ void XmlSerializer::ImportTriangles(XmlNode &node, aiMesh *mesh) {
mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1]; mesh->mMaterialIndex = baseMaterials->mMaterialIndex[p1];
} else if (it->second->getType() == ResourceType::RT_Texture2DGroup) { } else if (it->second->getType() == ResourceType::RT_Texture2DGroup) {
if (mesh->mTextureCoords[0] == nullptr) { if (mesh->mTextureCoords[0] == nullptr) {
Texture2DGroup *group = static_cast<Texture2DGroup *>(it->second); mesh->mNumUVComponents[0] = 2;
for (unsigned int i = 1; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
mesh->mNumUVComponents[i] = 0;
}
group = static_cast<Texture2DGroup *>(it->second);
const std::string name = ai_to_string(group->mTexId); const std::string name = ai_to_string(group->mTexId);
for (size_t i = 0; i < mMaterials.size(); ++i) { for (size_t i = 0; i < mMaterials.size(); ++i) {
if (name == mMaterials[i]->GetName().C_Str()) { if (name == mMaterials[i]->GetName().C_Str()) {
mesh->mMaterialIndex = static_cast<unsigned int>(i); mesh->mMaterialIndex = static_cast<unsigned int>(i);
} }
} }
mesh->mTextureCoords[0] = new aiVector3D[group->mTex2dCoords.size()]; mesh->mTextureCoords[0] = new aiVector3D[mesh->mNumVertices];
for (unsigned int i = 0; i < group->mTex2dCoords.size(); ++i) {
mesh->mTextureCoords[0][i] = aiVector3D(group->mTex2dCoords[i].x, group->mTex2dCoords[i].y, 0);
}
} }
} }
} }
} }
aiFace face = ReadTriangle(currentNode); // Load texture coordinates into mesh, when any
if (group != nullptr) {
size_t i0 = face.mIndices[0];
size_t i1 = face.mIndices[1];
size_t i2 = face.mIndices[2];
mesh->mTextureCoords[0][i0] = aiVector3D(group->mTex2dCoords[texId[0]].x, group->mTex2dCoords[texId[0]].y, 0.0f);
mesh->mTextureCoords[0][i1] = aiVector3D(group->mTex2dCoords[texId[1]].x, group->mTex2dCoords[texId[1]].y, 0.0f);
mesh->mTextureCoords[0][i2] = aiVector3D(group->mTex2dCoords[texId[2]].x, group->mTex2dCoords[texId[2]].y, 0.0f);
}
faces.push_back(face); faces.push_back(face);
} }
} }
@ -578,11 +597,15 @@ aiMaterial *XmlSerializer::readMaterialDef(XmlNode &node, unsigned int basemater
} }
void XmlSerializer::StoreMaterialsInScene(aiScene *scene) { void XmlSerializer::StoreMaterialsInScene(aiScene *scene) {
if (nullptr == scene || mMaterials.empty()) { if (nullptr == scene) {
return; return;
} }
scene->mNumMaterials = static_cast<unsigned int>(mMaterials.size()); scene->mNumMaterials = static_cast<unsigned int>(mMaterials.size());
if (scene->mNumMaterials == 0) {
return;
}
scene->mMaterials = new aiMaterial *[scene->mNumMaterials]; scene->mMaterials = new aiMaterial *[scene->mNumMaterials];
for (size_t i = 0; i < mMaterials.size(); ++i) { for (size_t i = 0; i < mMaterials.size(); ++i) {
scene->mMaterials[i] = mMaterials[i]; scene->mMaterials[i] = mMaterials[i];

View File

@ -621,6 +621,11 @@ struct Animation {
for (std::vector<Animation *>::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) { for (std::vector<Animation *>::iterator it = pParent->mSubAnims.begin(); it != pParent->mSubAnims.end();) {
Animation *anim = *it; Animation *anim = *it;
// Assign the first animation name to the parent if empty.
// This prevents the animation name from being lost when animations are combined
if (mName.empty()) {
mName = anim->mName;
}
CombineSingleChannelAnimationsRecursively(anim); CombineSingleChannelAnimationsRecursively(anim);
if (childrenAnimationsHaveDifferentChannels && anim->mChannels.size() == 1 && if (childrenAnimationsHaveDifferentChannels && anim->mChannels.size() == 1 &&

View File

@ -102,6 +102,7 @@ ColladaLoader::ColladaLoader() :
mTextures(), mTextures(),
mAnims(), mAnims(),
noSkeletonMesh(false), noSkeletonMesh(false),
removeEmptyBones(false),
ignoreUpDirection(false), ignoreUpDirection(false),
useColladaName(false), useColladaName(false),
mNodeNameCounter(0) { mNodeNameCounter(0) {
@ -130,6 +131,7 @@ bool ColladaLoader::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void ColladaLoader::SetupProperties(const Importer *pImp) { void ColladaLoader::SetupProperties(const Importer *pImp) {
noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES, 0) != 0; noSkeletonMesh = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_NO_SKELETON_MESHES, 0) != 0;
removeEmptyBones = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_REMOVE_EMPTY_BONES, true) != 0;
ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION, 0) != 0; ignoreUpDirection = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_IGNORE_UP_DIRECTION, 0) != 0;
useColladaName = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES, 0) != 0; useColladaName = pImp->GetPropertyInteger(AI_CONFIG_IMPORT_COLLADA_USE_COLLADA_NAMES, 0) != 0;
} }
@ -798,9 +800,10 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
// count the number of bones which influence vertices of the current submesh // count the number of bones which influence vertices of the current submesh
size_t numRemainingBones = 0; size_t numRemainingBones = 0;
for (const auto & dstBone : dstBones) { for (const auto & dstBone : dstBones) {
if (!dstBone.empty()) { if (dstBone.empty() && removeEmptyBones) {
++numRemainingBones; continue;
} }
++numRemainingBones;
} }
// create bone array and copy bone weights one by one // create bone array and copy bone weights one by one
@ -809,7 +812,7 @@ aiMesh *ColladaLoader::CreateMesh(const ColladaParser &pParser, const Mesh *pSrc
size_t boneCount = 0; size_t boneCount = 0;
for (size_t a = 0; a < numBones; ++a) { for (size_t a = 0; a < numBones; ++a) {
// omit bones without weights // omit bones without weights
if (dstBones[a].empty()) { if (dstBones[a].empty() && removeEmptyBones) {
continue; continue;
} }

View File

@ -237,6 +237,7 @@ protected:
std::vector<aiAnimation *> mAnims; std::vector<aiAnimation *> mAnims;
bool noSkeletonMesh; bool noSkeletonMesh;
bool removeEmptyBones;
bool ignoreUpDirection; bool ignoreUpDirection;
bool useColladaName; bool useColladaName;

View File

@ -368,7 +368,9 @@ void DXFImporter::ExpandBlockReferences(DXF::Block& bl,const DXF::BlockMap& bloc
// XXX this would be the place to implement recursive expansion if needed. // XXX this would be the place to implement recursive expansion if needed.
const DXF::Block& bl_src = *(*it).second; const DXF::Block& bl_src = *(*it).second;
for (std::shared_ptr<const DXF::PolyLine> pl_in : bl_src.lines) { const size_t size = bl_src.lines.size(); // the size may increase in the loop
for (size_t i = 0; i < size; ++i) {
std::shared_ptr<const DXF::PolyLine> pl_in = bl_src.lines[i];
if (!pl_in) { if (!pl_in) {
ASSIMP_LOG_ERROR("DXF: PolyLine instance is nullptr, skipping."); ASSIMP_LOG_ERROR("DXF: PolyLine instance is nullptr, skipping.");
continue; continue;

View File

@ -3377,6 +3377,10 @@ FBXConverter::KeyFrameListList FBXConverter::GetRotationKeyframeList(const std::
Keys->push_back(tnew); Keys->push_back(tnew);
Values->push_back(vnew); Values->push_back(vnew);
} }
else {
// Something broke
break;
}
tp = tnew; tp = tnew;
vp = vnew; vp = vnew;
} }

View File

@ -874,7 +874,7 @@ void IRRImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
// Batch loader used to load external models // Batch loader used to load external models
BatchLoader batch(pIOHandler); BatchLoader batch(pIOHandler);
// batch.SetBasePath(pFile); //batch.SetBasePath(pFile);
cameras.reserve(5); cameras.reserve(5);
lights.reserve(5); lights.reserve(5);

View File

@ -287,7 +287,7 @@ void LWOImporter::InternReadFile(const std::string &pFile,
if (UINT_MAX == iDefaultSurface) { if (UINT_MAX == iDefaultSurface) {
pSorted.erase(pSorted.end() - 1); pSorted.erase(pSorted.end() - 1);
} }
for (unsigned int p = 0, j = 0; j < mSurfaces->size(); ++j) { for (unsigned int j = 0; j < mSurfaces->size(); ++j) {
SortedRep &sorted = pSorted[j]; SortedRep &sorted = pSorted[j];
if (sorted.empty()) if (sorted.empty())
continue; continue;
@ -425,7 +425,6 @@ void LWOImporter::InternReadFile(const std::string &pFile,
} else { } else {
ASSIMP_LOG_VERBOSE_DEBUG("LWO2: No need to compute normals, they're already there"); ASSIMP_LOG_VERBOSE_DEBUG("LWO2: No need to compute normals, they're already there");
} }
++p;
} }
} }

View File

@ -313,6 +313,9 @@ void LWSImporter::SetupNodeName(aiNode *nd, LWS::NodeDesc &src) {
std::string::size_type t = src.path.substr(s).find_last_of('.'); std::string::size_type t = src.path.substr(s).find_last_of('.');
nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.path.substr(s).substr(0, t).c_str(), combined); nd->mName.length = ::ai_snprintf(nd->mName.data, MAXLEN, "%s_(%08X)", src.path.substr(s).substr(0, t).c_str(), combined);
if (nd->mName.length > MAXLEN) {
nd->mName.length = MAXLEN;
}
return; return;
} }
} }

View File

@ -449,6 +449,9 @@ void MDLImporter::ParseSkinLump_3DGS_MDL7(
unsigned int iWidth, unsigned int iWidth,
unsigned int iHeight) { unsigned int iHeight) {
std::unique_ptr<aiTexture> pcNew; std::unique_ptr<aiTexture> pcNew;
if (szCurrent == nullptr) {
return;
}
// get the type of the skin // get the type of the skin
unsigned int iMasked = (unsigned int)(iType & 0xF); unsigned int iMasked = (unsigned int)(iType & 0xF);

View File

@ -136,7 +136,9 @@ void NDOImporter::InternReadFile( const std::string& pFile,
ASSIMP_LOG_INFO("NDO file format is 1.2"); ASSIMP_LOG_INFO("NDO file format is 1.2");
} }
else { else {
ASSIMP_LOG_WARN( "Unrecognized nendo file format version, continuing happily ... :", (head+6)); char buff[4] = {0};
memcpy(buff, head+6, 3);
ASSIMP_LOG_WARN( "Unrecognized nendo file format version, continuing happily ... :", buff);
} }
reader.IncPtr(2); /* skip flags */ reader.IncPtr(2); /* skip flags */

View File

@ -126,17 +126,21 @@ void ObjFileMtlImporter::load() {
if (*m_DataIt == 'a') // Ambient color if (*m_DataIt == 'a') // Ambient color
{ {
++m_DataIt; ++m_DataIt;
getColorRGBA(&m_pModel->m_pCurrentMaterial->ambient); if (m_pModel->m_pCurrentMaterial != nullptr)
getColorRGBA(&m_pModel->m_pCurrentMaterial->ambient);
} else if (*m_DataIt == 'd') { } else if (*m_DataIt == 'd') {
// Diffuse color // Diffuse color
++m_DataIt; ++m_DataIt;
getColorRGBA(&m_pModel->m_pCurrentMaterial->diffuse); if (m_pModel->m_pCurrentMaterial != nullptr)
getColorRGBA(&m_pModel->m_pCurrentMaterial->diffuse);
} else if (*m_DataIt == 's') { } else if (*m_DataIt == 's') {
++m_DataIt; ++m_DataIt;
getColorRGBA(&m_pModel->m_pCurrentMaterial->specular); if (m_pModel->m_pCurrentMaterial != nullptr)
getColorRGBA(&m_pModel->m_pCurrentMaterial->specular);
} else if (*m_DataIt == 'e') { } else if (*m_DataIt == 'e') {
++m_DataIt; ++m_DataIt;
getColorRGBA(&m_pModel->m_pCurrentMaterial->emissive); if (m_pModel->m_pCurrentMaterial != nullptr)
getColorRGBA(&m_pModel->m_pCurrentMaterial->emissive);
} }
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} break; } break;
@ -145,13 +149,15 @@ void ObjFileMtlImporter::load() {
// Material transmission color // Material transmission color
if (*m_DataIt == 'f') { if (*m_DataIt == 'f') {
++m_DataIt; ++m_DataIt;
getColorRGBA(&m_pModel->m_pCurrentMaterial->transparent); if (m_pModel->m_pCurrentMaterial != nullptr)
getColorRGBA(&m_pModel->m_pCurrentMaterial->transparent);
} else if (*m_DataIt == 'r') { } else if (*m_DataIt == 'r') {
// Material transmission alpha value // Material transmission alpha value
++m_DataIt; ++m_DataIt;
ai_real d; ai_real d;
getFloatValue(d); getFloatValue(d);
m_pModel->m_pCurrentMaterial->alpha = static_cast<ai_real>(1.0) - d; if (m_pModel->m_pCurrentMaterial != nullptr)
m_pModel->m_pCurrentMaterial->alpha = static_cast<ai_real>(1.0) - d;
} }
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} break; } break;
@ -162,7 +168,8 @@ void ObjFileMtlImporter::load() {
} else { } else {
// Alpha value // Alpha value
++m_DataIt; ++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->alpha); if (m_pModel->m_pCurrentMaterial != nullptr)
getFloatValue(m_pModel->m_pCurrentMaterial->alpha);
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} }
} break; } break;
@ -173,11 +180,13 @@ void ObjFileMtlImporter::load() {
switch (*m_DataIt) { switch (*m_DataIt) {
case 's': // Specular exponent case 's': // Specular exponent
++m_DataIt; ++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->shineness); if (m_pModel->m_pCurrentMaterial != nullptr)
getFloatValue(m_pModel->m_pCurrentMaterial->shineness);
break; break;
case 'i': // Index Of refraction case 'i': // Index Of refraction
++m_DataIt; ++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->ior); if (m_pModel->m_pCurrentMaterial != nullptr)
getFloatValue(m_pModel->m_pCurrentMaterial->ior);
break; break;
case 'e': // New material case 'e': // New material
createMaterial(); createMaterial();
@ -197,23 +206,28 @@ void ObjFileMtlImporter::load() {
{ {
case 'r': case 'r':
++m_DataIt; ++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->roughness); if (m_pModel->m_pCurrentMaterial != nullptr)
getFloatValue(m_pModel->m_pCurrentMaterial->roughness);
break; break;
case 'm': case 'm':
++m_DataIt; ++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->metallic); if (m_pModel->m_pCurrentMaterial != nullptr)
getFloatValue(m_pModel->m_pCurrentMaterial->metallic);
break; break;
case 's': case 's':
++m_DataIt; ++m_DataIt;
getColorRGBA(m_pModel->m_pCurrentMaterial->sheen); if (m_pModel->m_pCurrentMaterial != nullptr)
getColorRGBA(m_pModel->m_pCurrentMaterial->sheen);
break; break;
case 'c': case 'c':
++m_DataIt; ++m_DataIt;
if (*m_DataIt == 'r') { if (*m_DataIt == 'r') {
++m_DataIt; ++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->clearcoat_roughness); if (m_pModel->m_pCurrentMaterial != nullptr)
getFloatValue(m_pModel->m_pCurrentMaterial->clearcoat_roughness);
} else { } else {
getFloatValue(m_pModel->m_pCurrentMaterial->clearcoat_thickness); if (m_pModel->m_pCurrentMaterial != nullptr)
getFloatValue(m_pModel->m_pCurrentMaterial->clearcoat_thickness);
} }
break; break;
} }
@ -232,7 +246,8 @@ void ObjFileMtlImporter::load() {
case 'i': // Illumination model case 'i': // Illumination model
{ {
m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd); m_DataIt = getNextToken<DataArrayIt>(m_DataIt, m_DataItEnd);
getIlluminationModel(m_pModel->m_pCurrentMaterial->illumination_model); if (m_pModel->m_pCurrentMaterial != nullptr)
getIlluminationModel(m_pModel->m_pCurrentMaterial->illumination_model);
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} break; } break;
@ -240,7 +255,8 @@ void ObjFileMtlImporter::load() {
{ {
++m_DataIt; ++m_DataIt;
getFloatValue(m_pModel->m_pCurrentMaterial->anisotropy); getFloatValue(m_pModel->m_pCurrentMaterial->anisotropy);
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine); if (m_pModel->m_pCurrentMaterial != nullptr)
m_DataIt = skipLine<DataArrayIt>(m_DataIt, m_DataItEnd, m_uiLine);
} break; } break;
default: { default: {

View File

@ -458,7 +458,8 @@ void ObjFileParser::getFace(aiPrimitiveType type) {
iPos = 0; iPos = 0;
} else { } else {
//OBJ USES 1 Base ARRAYS!!!! //OBJ USES 1 Base ARRAYS!!!!
const int iVal(::atoi(&(*m_DataIt))); std::string number(&(*m_DataIt), m_DataItEnd - m_DataIt);
const int iVal(::atoi(number.c_str()));
// increment iStep position based off of the sign and # of digits // increment iStep position based off of the sign and # of digits
int tmp = iVal; int tmp = iVal;

View File

@ -151,45 +151,46 @@ namespace Grammar {
} }
static TokenType matchTokenType(const char *tokenType) { static TokenType matchTokenType(const char *tokenType) {
if (MetricType == tokenType) { const size_t len = std::strlen(tokenType);
if (0 == strncmp(MetricType, tokenType, len)) {
return MetricToken; return MetricToken;
} else if (NameType == tokenType) { } else if (0 == strncmp(NameType, tokenType, len)) {
return NameToken; return NameToken;
} else if (ObjectRefType == tokenType) { } else if (0 == strncmp(ObjectRefType, tokenType, len)) {
return ObjectRefToken; return ObjectRefToken;
} else if (MaterialRefType == tokenType) { } else if (0 == strncmp(MaterialRefType, tokenType, len)) {
return MaterialRefToken; return MaterialRefToken;
} else if (MetricKeyType == tokenType) { } else if (0 == strncmp(MetricKeyType, tokenType, len)) {
return MetricKeyToken; return MetricKeyToken;
} else if (GeometryNodeType == tokenType) { } else if (0 == strncmp(GeometryNodeType, tokenType, len)) {
return GeometryNodeToken; return GeometryNodeToken;
} else if (CameraNodeType == tokenType) { } else if (0 == strncmp(CameraNodeType, tokenType, len)) {
return CameraNodeToken; return CameraNodeToken;
} else if (LightNodeType == tokenType) { } else if (0 == strncmp(LightNodeType, tokenType, len)) {
return LightNodeToken; return LightNodeToken;
} else if (GeometryObjectType == tokenType) { } else if (0 == strncmp(GeometryObjectType, tokenType, len)) {
return GeometryObjectToken; return GeometryObjectToken;
} else if (CameraObjectType == tokenType) { } else if (0 == strncmp(CameraObjectType, tokenType, len)) {
return CameraObjectToken; return CameraObjectToken;
} else if (LightObjectType == tokenType) { } else if (0 == strncmp(LightObjectType, tokenType, len)) {
return LightObjectToken; return LightObjectToken;
} else if (TransformType == tokenType) { } else if (0 == strncmp(TransformType, tokenType, len)) {
return TransformToken; return TransformToken;
} else if (MeshType == tokenType) { } else if (0 == strncmp(MeshType, tokenType, len)) {
return MeshToken; return MeshToken;
} else if (VertexArrayType == tokenType) { } else if (0 == strncmp(VertexArrayType, tokenType, len)) {
return VertexArrayToken; return VertexArrayToken;
} else if (IndexArrayType == tokenType) { } else if (0 == strncmp(IndexArrayType, tokenType, len)) {
return IndexArrayToken; return IndexArrayToken;
} else if (MaterialType == tokenType) { } else if (0 == strncmp(MaterialType, tokenType, len)) {
return MaterialToken; return MaterialToken;
} else if (ColorType == tokenType) { } else if (0 == strncmp(ColorType, tokenType, len)) {
return ColorToken; return ColorToken;
} else if (ParamType == tokenType) { } else if (0 == strncmp(ParamType, tokenType, len)) {
return ParamToken; return ParamToken;
} else if (TextureType == tokenType) { } else if (0 == strncmp(TextureType, tokenType, len)) {
return TextureToken; return TextureToken;
} else if (AttenType == tokenType) { } else if (0 == strncmp(AttenType, tokenType, len)) {
return AttenToken; return AttenToken;
} }
@ -256,11 +257,6 @@ OpenGEXImporter::RefInfo::RefInfo(aiNode *node, Type type, std::vector<std::stri
// empty // empty
} }
//------------------------------------------------------------------------------------------------
OpenGEXImporter::RefInfo::~RefInfo() {
// empty
}
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
OpenGEXImporter::OpenGEXImporter() : OpenGEXImporter::OpenGEXImporter() :
m_root(nullptr), m_root(nullptr),
@ -285,10 +281,6 @@ OpenGEXImporter::OpenGEXImporter() :
// empty // empty
} }
//------------------------------------------------------------------------------------------------
OpenGEXImporter::~OpenGEXImporter() {
}
//------------------------------------------------------------------------------------------------ //------------------------------------------------------------------------------------------------
bool OpenGEXImporter::CanRead(const std::string &file, IOSystem *pIOHandler, bool /*checkSig*/) const { bool OpenGEXImporter::CanRead(const std::string &file, IOSystem *pIOHandler, bool /*checkSig*/) const {
static const char *tokens[] = { "Metric", "GeometryNode", "VertexArray (attrib", "IndexArray" }; static const char *tokens[] = { "Metric", "GeometryNode", "VertexArray (attrib", "IndexArray" };

View File

@ -79,12 +79,7 @@ struct MetricInfo {
float m_floatValue; float m_floatValue;
int m_intValue; int m_intValue;
MetricInfo() MetricInfo(): m_stringValue( ), m_floatValue( 0.0f ), m_intValue( -1 ) {}
: m_stringValue( )
, m_floatValue( 0.0f )
, m_intValue( -1 ) {
// empty
}
}; };
/** @brief This class is used to implement the OpenGEX importer /** @brief This class is used to implement the OpenGEX importer
@ -97,7 +92,7 @@ public:
OpenGEXImporter(); OpenGEXImporter();
/// The class destructor. /// The class destructor.
~OpenGEXImporter() override; ~OpenGEXImporter() override = default;
/// BaseImporter override. /// BaseImporter override.
bool CanRead( const std::string &file, IOSystem *pIOHandler, bool checkSig ) const override; bool CanRead( const std::string &file, IOSystem *pIOHandler, bool checkSig ) const override;
@ -170,7 +165,7 @@ private:
std::vector<std::string> m_Names; std::vector<std::string> m_Names;
RefInfo( aiNode *node, Type type, std::vector<std::string> &names ); RefInfo( aiNode *node, Type type, std::vector<std::string> &names );
~RefInfo(); ~RefInfo() = default;
RefInfo( const RefInfo & ) = delete; RefInfo( const RefInfo & ) = delete;
RefInfo &operator = ( const RefInfo & ) = delete; RefInfo &operator = ( const RefInfo & ) = delete;

View File

@ -129,10 +129,20 @@ void Q3DImporter::InternReadFile(const std::string &pFile,
unsigned int numTextures = (unsigned int)stream.GetI4(); unsigned int numTextures = (unsigned int)stream.GetI4();
std::vector<Material> materials; std::vector<Material> materials;
materials.reserve(numMats); try {
materials.reserve(numMats);
} catch(const std::bad_alloc&) {
ASSIMP_LOG_ERROR("Invalid alloc for materials.");
throw DeadlyImportError("Invalid Quick3D-file, material allocation failed.");
}
std::vector<Mesh> meshes; std::vector<Mesh> meshes;
meshes.reserve(numMeshes); try {
meshes.reserve(numMeshes);
} catch(const std::bad_alloc&) {
ASSIMP_LOG_ERROR("Invalid alloc for meshes.");
throw DeadlyImportError("Invalid Quick3D-file, mesh allocation failed.");
}
// Allocate the scene root node // Allocate the scene root node
pScene->mRootNode = new aiNode(); pScene->mRootNode = new aiNode();

View File

@ -73,7 +73,7 @@ static const aiImporterDesc desc = {
// 1) 80 byte header // 1) 80 byte header
// 2) 4 byte face count // 2) 4 byte face count
// 3) 50 bytes per face // 3) 50 bytes per face
static bool IsBinarySTL(const char *buffer, unsigned int fileSize) { static bool IsBinarySTL(const char *buffer, size_t fileSize) {
if (fileSize < 84) { if (fileSize < 84) {
return false; return false;
} }
@ -92,7 +92,7 @@ static const char UnicodeBoundary = 127;
// An ascii STL buffer will begin with "solid NAME", where NAME is optional. // An ascii STL buffer will begin with "solid NAME", where NAME is optional.
// Note: The "solid NAME" check is necessary, but not sufficient, to determine // Note: The "solid NAME" check is necessary, but not sufficient, to determine
// if the buffer is ASCII; a binary header could also begin with "solid NAME". // if the buffer is ASCII; a binary header could also begin with "solid NAME".
static bool IsAsciiSTL(const char *buffer, unsigned int fileSize) { static bool IsAsciiSTL(const char *buffer, size_t fileSize) {
if (IsBinarySTL(buffer, fileSize)) if (IsBinarySTL(buffer, fileSize))
return false; return false;
@ -172,7 +172,7 @@ void STLImporter::InternReadFile(const std::string &pFile, aiScene *pScene, IOSy
throw DeadlyImportError("Failed to open STL file ", pFile, "."); throw DeadlyImportError("Failed to open STL file ", pFile, ".");
} }
mFileSize = (unsigned int)file->FileSize(); mFileSize = file->FileSize();
// allocate storage and copy the contents of the file to a memory buffer // allocate storage and copy the contents of the file to a memory buffer
// (terminate it with zero) // (terminate it with zero)
@ -233,7 +233,7 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
// try to guess how many vertices we could have // try to guess how many vertices we could have
// assume we'll need 160 bytes for each face // assume we'll need 160 bytes for each face
size_t sizeEstimate = std::max(1u, mFileSize / 160u) * 3; size_t sizeEstimate = std::max(1ull, mFileSize / 160ull) * 3ull;
positionBuffer.reserve(sizeEstimate); positionBuffer.reserve(sizeEstimate);
normalBuffer.reserve(sizeEstimate); normalBuffer.reserve(sizeEstimate);
@ -284,8 +284,6 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
ASSIMP_LOG_WARN("STL: A new facet begins but the old is not yet complete"); ASSIMP_LOG_WARN("STL: A new facet begins but the old is not yet complete");
} }
faceVertexCounter = 0; faceVertexCounter = 0;
normalBuffer.push_back(aiVector3D());
aiVector3D *vn = &normalBuffer.back();
sz += 6; sz += 6;
SkipSpaces(&sz); SkipSpaces(&sz);
@ -295,15 +293,17 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
if (sz[6] == '\0') { if (sz[6] == '\0') {
throw DeadlyImportError("STL: unexpected EOF while parsing facet"); throw DeadlyImportError("STL: unexpected EOF while parsing facet");
} }
aiVector3D vn;
sz += 7; sz += 7;
SkipSpaces(&sz); SkipSpaces(&sz);
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn->x); sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn.x);
SkipSpaces(&sz); SkipSpaces(&sz);
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn->y); sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn.y);
SkipSpaces(&sz); SkipSpaces(&sz);
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn->z); sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn.z);
normalBuffer.push_back(*vn); normalBuffer.emplace_back(vn);
normalBuffer.push_back(*vn); normalBuffer.emplace_back(vn);
normalBuffer.emplace_back(vn);
} }
} else if (!strncmp(sz, "vertex", 6) && ::IsSpaceOrNewLine(*(sz + 6))) { // vertex 1.50000 1.50000 0.00000 } else if (!strncmp(sz, "vertex", 6) && ::IsSpaceOrNewLine(*(sz + 6))) { // vertex 1.50000 1.50000 0.00000
if (faceVertexCounter >= 3) { if (faceVertexCounter >= 3) {
@ -315,7 +315,7 @@ void STLImporter::LoadASCIIFile(aiNode *root) {
} }
sz += 7; sz += 7;
SkipSpaces(&sz); SkipSpaces(&sz);
positionBuffer.push_back(aiVector3D()); positionBuffer.emplace_back();
aiVector3D *vn = &positionBuffer.back(); aiVector3D *vn = &positionBuffer.back();
sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn->x); sz = fast_atoreal_move<ai_real>(sz, (ai_real &)vn->x);
SkipSpaces(&sz); SkipSpaces(&sz);
@ -439,7 +439,7 @@ bool STLImporter::LoadBinaryFile() {
pMesh->mNumFaces = *((uint32_t *)sz); pMesh->mNumFaces = *((uint32_t *)sz);
sz += 4; sz += 4;
if (mFileSize < 84 + pMesh->mNumFaces * 50) { if (mFileSize < 84ull + pMesh->mNumFaces * 50ull) {
throw DeadlyImportError("STL: file is too small to hold all facets"); throw DeadlyImportError("STL: file is too small to hold all facets");
} }
@ -517,13 +517,13 @@ bool STLImporter::LoadBinaryFile() {
const ai_real invVal((ai_real)1.0 / (ai_real)31.0); const ai_real invVal((ai_real)1.0 / (ai_real)31.0);
if (bIsMaterialise) // this is reversed if (bIsMaterialise) // this is reversed
{ {
clr->r = (color & 0x31u) * invVal; clr->r = (color & 0x1fu) * invVal;
clr->g = ((color & (0x31u << 5)) >> 5u) * invVal; clr->g = ((color & (0x1fu << 5)) >> 5u) * invVal;
clr->b = ((color & (0x31u << 10)) >> 10u) * invVal; clr->b = ((color & (0x1fu << 10)) >> 10u) * invVal;
} else { } else {
clr->b = (color & 0x31u) * invVal; clr->b = (color & 0x1fu) * invVal;
clr->g = ((color & (0x31u << 5)) >> 5u) * invVal; clr->g = ((color & (0x1fu << 5)) >> 5u) * invVal;
clr->r = ((color & (0x31u << 10)) >> 10u) * invVal; clr->r = ((color & (0x1fu << 10)) >> 10u) * invVal;
} }
// assign the color to all vertices of the face // assign the color to all vertices of the face
*(clr + 1) = *clr; *(clr + 1) = *clr;

View File

@ -109,7 +109,7 @@ protected:
const char* mBuffer; const char* mBuffer;
/** Size of the file, in bytes */ /** Size of the file, in bytes */
unsigned int mFileSize; size_t mFileSize;
/** Output scene */ /** Output scene */
aiScene* mScene; aiScene* mScene;

View File

@ -2,8 +2,7 @@
Open Asset Import Library (assimp) Open Asset Import Library (assimp)
---------------------------------------------------------------------- ----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team Copyright (c) 2006-2022, assimp team
All rights reserved. All rights reserved.
@ -59,7 +58,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# pragma warning(disable : 4127 4456 4245 4512 ) # pragma warning(disable : 4127 4456 4245 4512 )
#endif // _MSC_VER #endif // _MSC_VER
//
#if _MSC_VER > 1500 || (defined __GNUC___) #if _MSC_VER > 1500 || (defined __GNUC___)
# define ASSIMP_STEP_USE_UNORDERED_MULTIMAP # define ASSIMP_STEP_USE_UNORDERED_MULTIMAP
#else #else
@ -99,13 +97,9 @@ namespace EXPRESS {
class DataType; class DataType;
class UNSET; /*: public DataType */ class UNSET; /*: public DataType */
class ISDERIVED; /*: public DataType */ class ISDERIVED; /*: public DataType */
// class REAL; /*: public DataType */
class ENUM; /*: public DataType */ class ENUM; /*: public DataType */
// class STRING; /*: public DataType */
// class INTEGER; /*: public DataType */
class ENTITY; /*: public DataType */ class ENTITY; /*: public DataType */
class LIST; /*: public DataType */ class LIST; /*: public DataType */
// class SELECT; /*: public DataType */
// a conversion schema is not exactly an EXPRESS schema, rather it // a conversion schema is not exactly an EXPRESS schema, rather it
// is a list of pointers to conversion functions to build up the // is a list of pointers to conversion functions to build up the
@ -127,7 +121,8 @@ namespace STEP {
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** Exception class used by the STEP loading & parsing code. It is typically /** Exception class used by the STEP loading & parsing code. It is typically
* coupled with a line number. */ * coupled with a line number.
*/
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct SyntaxError : DeadlyImportError { struct SyntaxError : DeadlyImportError {
enum : uint64_t { enum : uint64_t {
@ -139,8 +134,9 @@ struct SyntaxError : DeadlyImportError {
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** Exception class used by the STEP loading & parsing code when a type /** Exception class used by the STEP loading & parsing code when a type
* error (i.e. an entity expects a string but receives a bool) occurs. * error (i.e. an entity expects a string but receives a bool) occurs.
* It is typically coupled with both an entity id and a line number.*/ * It is typically coupled with both an entity id and a line number.
*/
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
struct TypeError : DeadlyImportError { struct TypeError : DeadlyImportError {
enum : uint64_t { enum : uint64_t {
@ -167,10 +163,8 @@ public:
typedef std::shared_ptr<const DataType> Out; typedef std::shared_ptr<const DataType> Out;
public: public:
virtual ~DataType() { virtual ~DataType() = default;
}
public:
template <typename T> template <typename T>
const T &To() const { const T &To() const {
return dynamic_cast<const T &>(*this); return dynamic_cast<const T &>(*this);
@ -206,16 +200,14 @@ public:
public: public:
/** parse a variable from a string and set 'inout' to the character /** parse a variable from a string and set 'inout' to the character
* behind the last consumed character. An optional schema enables, * behind the last consumed character. An optional schema enables,
* if specified, automatic conversion of custom data types. * if specified, automatic conversion of custom data types.
* *
* @throw SyntaxError * @throw SyntaxError
*/ */
static std::shared_ptr<const EXPRESS::DataType> Parse(const char *&inout, static std::shared_ptr<const EXPRESS::DataType> Parse(const char *&inout,
uint64_t line = SyntaxError::LINE_NOT_SPECIFIED, uint64_t line = SyntaxError::LINE_NOT_SPECIFIED,
const EXPRESS::ConversionSchema *schema = NULL); const EXPRESS::ConversionSchema *schema = NULL);
public:
}; };
typedef DataType SELECT; typedef DataType SELECT;
@ -238,7 +230,8 @@ private:
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** Shared implementation for some of the primitive data type, i.e. int, float */ /** Shared implementation for some of the primitive data type, i.e. int, float
*/
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
template <typename T> template <typename T>
class PrimitiveDataType : public DataType { class PrimitiveDataType : public DataType {
@ -247,7 +240,7 @@ public:
// expose this data type to the user. // expose this data type to the user.
typedef T Out; typedef T Out;
PrimitiveDataType() {} PrimitiveDataType() = default;
PrimitiveDataType(const T &val) : PrimitiveDataType(const T &val) :
val(val) {} val(val) {}
@ -280,28 +273,18 @@ class ENUMERATION : public STRING {
public: public:
ENUMERATION(const std::string &val) : ENUMERATION(const std::string &val) :
STRING(val) {} STRING(val) {}
private:
}; };
typedef ENUMERATION BOOLEAN; typedef ENUMERATION BOOLEAN;
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/** This is just a reference to an entity/object somewhere else */ /** This is just a reference to an entity/object somewhere else
*/
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
class ENTITY : public PrimitiveDataType<uint64_t> { class ENTITY : public PrimitiveDataType<uint64_t> {
public: public:
ENTITY(uint64_t val) : ENTITY(uint64_t val) : PrimitiveDataType<uint64_t>(val) {}
PrimitiveDataType<uint64_t>(val) { ENTITY() : PrimitiveDataType<uint64_t>(TypeError::ENTITY_NOT_SPECIFIED) {}
ai_assert(val != 0);
}
ENTITY() :
PrimitiveDataType<uint64_t>(TypeError::ENTITY_NOT_SPECIFIED) {
// empty
}
private:
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
@ -319,7 +302,8 @@ public:
} }
public: public:
/** @see DaraType::Parse */ /** @see DaraType::Parse
*/
static std::shared_ptr<const EXPRESS::LIST> Parse(const char *&inout, static std::shared_ptr<const EXPRESS::LIST> Parse(const char *&inout,
uint64_t line = SyntaxError::LINE_NOT_SPECIFIED, uint64_t line = SyntaxError::LINE_NOT_SPECIFIED,
const EXPRESS::ConversionSchema *schema = NULL); const EXPRESS::ConversionSchema *schema = NULL);
@ -331,29 +315,20 @@ private:
class BINARY : public PrimitiveDataType<uint32_t> { class BINARY : public PrimitiveDataType<uint32_t> {
public: public:
BINARY(uint32_t val) : BINARY(uint32_t val) : PrimitiveDataType<uint32_t>(val) {}
PrimitiveDataType<uint32_t>(val) { BINARY() : PrimitiveDataType<uint32_t>(TypeError::ENTITY_NOT_SPECIFIED_32) {}
// empty
}
BINARY() :
PrimitiveDataType<uint32_t>(TypeError::ENTITY_NOT_SPECIFIED_32) {
// empty
}
}; };
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
/* Not exactly a full EXPRESS schema but rather a list of conversion functions /* Not exactly a full EXPRESS schema but rather a list of conversion functions
* to extract valid C++ objects out of a STEP file. Those conversion functions * to extract valid C++ objects out of a STEP file. Those conversion functions
* may, however, perform further schema validations. */ * may, however, perform further schema validations.
*/
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
class ConversionSchema { class ConversionSchema {
public: public:
struct SchemaEntry { struct SchemaEntry {
SchemaEntry(const char *name, ConvertObjectProc func) : SchemaEntry(const char *name, ConvertObjectProc func) : mName(name), mFunc(func) {}
mName(name), mFunc(func) {
// empty
}
const char *mName; const char *mName;
ConvertObjectProc mFunc; ConvertObjectProc mFunc;
@ -366,8 +341,7 @@ public:
*this = schemas; *this = schemas;
} }
ConversionSchema() { ConversionSchema() = default;
}
ConvertObjectProc GetConverterProc(const std::string &name) const { ConvertObjectProc GetConverterProc(const std::string &name) const {
ConverterMap::const_iterator it = converters.find(name); ConverterMap::const_iterator it = converters.find(name);
@ -399,8 +373,9 @@ private:
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
/** Bundle all the relevant info from a STEP header, parts of which may later /** Bundle all the relevant info from a STEP header, parts of which may later
* be plainly dumped to the logfile, whereas others may help the caller pick an * be plainly dumped to the logfile, whereas others may help the caller pick an
* appropriate loading strategy.*/ * appropriate loading strategy.
*/
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
struct HeaderInfo { struct HeaderInfo {
std::string timestamp; std::string timestamp;
@ -409,18 +384,14 @@ struct HeaderInfo {
}; };
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
/** Base class for all concrete object instances */ /** Base class for all concrete object instances
*/
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
class Object { class Object {
public: public:
Object(const char *classname = "unknown") : Object(const char *classname = "unknown") : id(0), classname(classname) {}
id(0), classname(classname) {
// empty
}
virtual ~Object() { virtual ~Object() = default;
// empty
}
// utilities to simplify casting to concrete types // utilities to simplify casting to concrete types
template <typename T> template <typename T>
@ -469,26 +440,15 @@ size_t GenericFill(const STEP::DB &db, const EXPRESS::LIST &params, T *in);
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
template <typename TDerived, size_t arg_count> template <typename TDerived, size_t arg_count>
struct ObjectHelper : virtual Object { struct ObjectHelper : virtual Object {
ObjectHelper() : ObjectHelper() : aux_is_derived(0) {}
aux_is_derived(0) {
// empty
}
static Object *Construct(const STEP::DB &db, const EXPRESS::LIST &params) { static Object *Construct(const STEP::DB &db, const EXPRESS::LIST &params) {
// make sure we don't leak if Fill() throws an exception // make sure we don't leak if Fill() throws an exception
std::unique_ptr<TDerived> impl(new TDerived()); std::unique_ptr<TDerived> impl(new TDerived());
// GenericFill<T> is undefined so we need to have a specialization // GenericFill<T> is undefined so we need to have a specialization
const size_t num_args = GenericFill<TDerived>(db, params, &*impl); static_cast<void>(GenericFill<TDerived>(db, params, &*impl));
(void)num_args;
// the following check is commented because it will always trigger if
// parts of the entities are generated with dummy wrapper code.
// This is currently done to reduce the size of the loader
// code.
//if (num_args != params.GetSize() && impl->GetClassName() != "NotImplemented") {
// DefaultLogger::get()->debug("STEP: not all parameters consumed");
//}
return impl.release(); return impl.release();
} }
@ -502,15 +462,9 @@ struct ObjectHelper : virtual Object {
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
template <typename T> template <typename T>
struct Maybe { struct Maybe {
Maybe() : Maybe() : have() {}
have() {
// empty
}
explicit Maybe(const T &ptr) : explicit Maybe(const T &ptr) : ptr(ptr), have(true) {}
ptr(ptr), have(true) {
// empty
}
void flag_invalid() { void flag_invalid() {
have = false; have = false;
@ -557,7 +511,8 @@ private:
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
/** A LazyObject is created when needed. Before this happens, we just keep /** A LazyObject is created when needed. Before this happens, we just keep
the text line that contains the object definition. */ * the text line that contains the object definition.
*/
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
class LazyObject { class LazyObject {
friend class DB; friend class DB;
@ -649,10 +604,7 @@ inline bool operator==(const std::pair<uint64_t, std::shared_ptr<LazyObject>> &l
template <typename T> template <typename T>
struct Lazy { struct Lazy {
typedef Lazy Out; typedef Lazy Out;
Lazy(const LazyObject *obj = nullptr) : Lazy(const LazyObject *obj = nullptr) : obj(obj) {}
obj(obj) {
// empty
}
operator const T *() const { operator const T *() const {
return obj->ToPtr<T>(); return obj->ToPtr<T>();
@ -785,8 +737,9 @@ inline void GenericConvert(ListOf<T1, N1, N2> &a, const std::shared_ptr<const EX
// ------------------------------------------------------------------------------ // ------------------------------------------------------------------------------
/** Lightweight manager class that holds the map of all objects in a /** Lightweight manager class that holds the map of all objects in a
* STEP file. DB's are exclusively maintained by the functions in * STEP file. DB's are exclusively maintained by the functions in
* STEPFileReader.h*/ * STEPFileReader.h
*/
// ------------------------------------------------------------------------------- // -------------------------------------------------------------------------------
class DB { class DB {
friend DB *ReadFileHeader(std::shared_ptr<IOStream> stream); friend DB *ReadFileHeader(std::shared_ptr<IOStream> stream);
@ -873,7 +826,7 @@ public:
if (it != objects_bytype.end() && (*it).second.size()) { if (it != objects_bytype.end() && (*it).second.size()) {
return *(*it).second.begin(); return *(*it).second.begin();
} }
return NULL; return nullptr;
} }
// same, but raise an exception if the object doesn't exist and return a reference // same, but raise an exception if the object doesn't exist and return a reference
@ -965,7 +918,6 @@ private:
#endif // _MSC_VER #endif // _MSC_VER
} // namespace STEP } // namespace STEP
} // namespace Assimp } // namespace Assimp
#endif // INCLUDED_AI_STEPFILE_H #endif // INCLUDED_AI_STEPFILE_H

View File

@ -683,7 +683,7 @@ bool glTF2Exporter::GetMatSheen(const aiMaterial &mat, glTF2::MaterialSheen &she
} }
// Default Sheen color factor {0,0,0} disables Sheen, so do not export // Default Sheen color factor {0,0,0} disables Sheen, so do not export
if (sheen.sheenColorFactor == defaultSheenFactor) { if (sheen.sheenColorFactor[0] == defaultSheenFactor[0] && sheen.sheenColorFactor[1] == defaultSheenFactor[1] && sheen.sheenColorFactor[2] == defaultSheenFactor[2]) {
return false; return false;
} }

View File

@ -63,7 +63,7 @@ inline int select_fseek(FILE *file, int64_t offset, int origin) {
#if defined _WIN64 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601) #if defined _WIN32 && (!defined __GNUC__ || !defined __CLANG__ && __MSVCRT_VERSION__ >= 0x0601)
template <> template <>
inline size_t select_ftell<8>(FILE *file) { inline size_t select_ftell<8>(FILE *file) {
return (size_t)::_ftelli64(file); return (size_t)::_ftelli64(file);
@ -74,7 +74,7 @@ inline int select_fseek<8>(FILE *file, int64_t offset, int origin) {
return ::_fseeki64(file, offset, origin); return ::_fseeki64(file, offset, origin);
} }
#endif // #if defined _WIN32 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601) #endif
} // namespace } // namespace
@ -149,13 +149,20 @@ size_t DefaultIOStream::FileSize() const {
// //
// See here for details: // See here for details:
// https://www.securecoding.cert.org/confluence/display/seccode/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+of+a+regular+file // https://www.securecoding.cert.org/confluence/display/seccode/FIO19-C.+Do+not+use+fseek()+and+ftell()+to+compute+the+size+of+a+regular+file
#if defined _WIN64 && (!defined __GNUC__ || __MSVCRT_VERSION__ >= 0x0601) #if defined _WIN32 && (!defined __GNUC__ || !defined __CLANG__ && __MSVCRT_VERSION__ >= 0x0601)
struct __stat64 fileStat; struct __stat64 fileStat;
//using fileno + fstat avoids having to handle the filename //using fileno + fstat avoids having to handle the filename
int err = _fstat64(_fileno(mFile), &fileStat); int err = _fstat64(_fileno(mFile), &fileStat);
if (0 != err) if (0 != err)
return 0; return 0;
mCachedSize = (size_t)(fileStat.st_size); mCachedSize = (size_t)(fileStat.st_size);
#elif defined _WIN32
struct _stat32 fileStat;
//using fileno + fstat avoids having to handle the filename
int err = _fstat32(_fileno(mFile), &fileStat);
if (0 != err)
return 0;
mCachedSize = (size_t)(fileStat.st_size);
#elif defined __GNUC__ || defined __APPLE__ || defined __MACH__ || defined __FreeBSD__ #elif defined __GNUC__ || defined __APPLE__ || defined __MACH__ || defined __FreeBSD__
struct stat fileStat; struct stat fileStat;
int err = stat(mFilename.c_str(), &fileStat); int err = stat(mFilename.c_str(), &fileStat);

View File

@ -105,36 +105,39 @@ void ScenePreprocessor::ProcessMesh(aiMesh *mesh) {
for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) { for (unsigned int i = 0; i < AI_MAX_NUMBER_OF_TEXTURECOORDS; ++i) {
if (!mesh->mTextureCoords[i]) { if (!mesh->mTextureCoords[i]) {
mesh->mNumUVComponents[i] = 0; mesh->mNumUVComponents[i] = 0;
} else { continue;
if (!mesh->mNumUVComponents[i]) { }
mesh->mNumUVComponents[i] = 2;
if (!mesh->mNumUVComponents[i]) {
mesh->mNumUVComponents[i] = 2;
}
aiVector3D *p = mesh->mTextureCoords[i], *end = p + mesh->mNumVertices;
// Ensure unused components are zeroed. This will make 1D texture channels work
// as if they were 2D channels .. just in case an application doesn't handle
// this case
if (2 == mesh->mNumUVComponents[i]) {
size_t num = 0;
for (; p != end; ++p) {
p->z = 0.f;
num++;
} }
} else if (1 == mesh->mNumUVComponents[i]) {
aiVector3D *p = mesh->mTextureCoords[i], *end = p + mesh->mNumVertices; for (; p != end; ++p) {
p->z = p->y = 0.f;
// Ensure unused components are zeroed. This will make 1D texture channels work }
// as if they were 2D channels .. just in case an application doesn't handle } else if (3 == mesh->mNumUVComponents[i]) {
// this case // Really 3D coordinates? Check whether the third coordinate is != 0 for at least one element
if (2 == mesh->mNumUVComponents[i]) { for (; p != end; ++p) {
for (; p != end; ++p) { if (p->z != 0) {
p->z = 0.f; break;
}
} else if (1 == mesh->mNumUVComponents[i]) {
for (; p != end; ++p) {
p->z = p->y = 0.f;
}
} else if (3 == mesh->mNumUVComponents[i]) {
// Really 3D coordinates? Check whether the third coordinate is != 0 for at least one element
for (; p != end; ++p) {
if (p->z != 0) {
break;
}
}
if (p == end) {
ASSIMP_LOG_WARN("ScenePreprocessor: UVs are declared to be 3D but they're obviously not. Reverting to 2D.");
mesh->mNumUVComponents[i] = 2;
} }
} }
if (p == end) {
ASSIMP_LOG_WARN("ScenePreprocessor: UVs are declared to be 3D but they're obviously not. Reverting to 2D.");
mesh->mNumUVComponents[i] = 2;
}
} }
} }

View File

@ -196,7 +196,9 @@ zlib_filefunc_def IOSystem2Unzip::get(IOSystem *pIOHandler) {
zlib_filefunc_def mapping; zlib_filefunc_def mapping;
mapping.zopen_file = (open_file_func)open; mapping.zopen_file = (open_file_func)open;
#ifdef _UNZ_H
mapping.zopendisk_file = (opendisk_file_func)opendisk; mapping.zopendisk_file = (opendisk_file_func)opendisk;
#endif
mapping.zread_file = (read_file_func)read; mapping.zread_file = (read_file_func)read;
mapping.zwrite_file = (write_file_func)write; mapping.zwrite_file = (write_file_func)write;
mapping.ztell_file = (tell_file_func)tell; mapping.ztell_file = (tell_file_func)tell;

View File

@ -128,7 +128,7 @@ bool EmbedTexturesProcess::addTexture(aiScene *pScene, const std::string &path)
aiTexel* imageContent = new aiTexel[ 1ul + static_cast<unsigned long>( imageSize ) / sizeof(aiTexel)]; aiTexel* imageContent = new aiTexel[ 1ul + static_cast<unsigned long>( imageSize ) / sizeof(aiTexel)];
pFile->Seek(0, aiOrigin_SET); pFile->Seek(0, aiOrigin_SET);
pFile->Read(reinterpret_cast<char*>(imageContent), imageSize, 1); pFile->Read(reinterpret_cast<char*>(imageContent), static_cast<size_t>(imageSize), 1);
mIOHandler->Close(pFile); mIOHandler->Close(pFile);
// Enlarging the textures table // Enlarging the textures table

View File

@ -1,5 +1,9 @@
#include "revision.h" #include "revision.h"
#ifdef __GNUC__
#include "winresrc.h"
#else
#include "winres.h" #include "winres.h"
#endif
LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#pragma code_page(1252) #pragma code_page(1252)

View File

@ -4941,7 +4941,7 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
{ {
stbi_uc palette[1024], pal_img_n=0; stbi_uc palette[1024], pal_img_n=0;
stbi_uc has_trans=0, tc[3]={0}; stbi_uc has_trans=0, tc[3]={0};
stbi__uint16 tc16[3]; stbi__uint16 tc16[3]={0};
stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0; stbi__uint32 ioff=0, idata_limit=0, i, pal_len=0;
int first=1,k,interlace=0, color=0, is_iphone=0; int first=1,k,interlace=0, color=0, is_iphone=0;
stbi__context *s = z->s; stbi__context *s = z->s;

View File

@ -99,295 +99,129 @@ template <class TNodeType>
class TXmlParser { class TXmlParser {
public: public:
/// @brief The default class constructor. /// @brief The default class constructor.
TXmlParser() : TXmlParser();
mDoc(nullptr),
mData() {
// empty
}
/// @brief The class destructor. /// @brief The class destructor.
~TXmlParser() { ~TXmlParser();
clear();
}
/// @brief Will clear the parsed xml-file. /// @brief Will clear the parsed xml-file.
void clear() { void clear();
if (mData.empty()) {
mDoc = nullptr;
return;
}
mData.clear();
delete mDoc;
mDoc = nullptr;
}
/// @brief Will search for a child-node by its name /// @brief Will search for a child-node by its name
/// @param name [in] The name of the child-node. /// @param name [in] The name of the child-node.
/// @return The node instance or nullptr, if nothing was found. /// @return The node instance or nullptr, if nothing was found.
TNodeType *findNode(const std::string &name) { TNodeType *findNode(const std::string &name);
if (name.empty()) {
return nullptr;
}
if (nullptr == mDoc) {
return nullptr;
}
find_node_by_name_predicate predicate(name);
mCurrent = mDoc->find_node(predicate);
if (mCurrent.empty()) {
return nullptr;
}
return &mCurrent;
}
/// @brief Will return true, if the node is a child-node. /// @brief Will return true, if the node is a child-node.
/// @param name [in] The name of the child node to look for. /// @param name [in] The name of the child node to look for.
/// @return true, if the node is a child-node or false if not. /// @return true, if the node is a child-node or false if not.
bool hasNode(const std::string &name) { bool hasNode(const std::string &name);
return nullptr != findNode(name);
}
/// @brief Will parse an xml-file from a given stream. /// @brief Will parse an xml-file from a given stream.
/// @param stream The input stream. /// @param stream The input stream.
/// @return true, if the parsing was successful, false if not. /// @return true, if the parsing was successful, false if not.
bool parse(IOStream *stream) { bool parse(IOStream *stream);
if (nullptr == stream) {
ASSIMP_LOG_DEBUG("Stream is nullptr.");
return false;
}
const size_t len = stream->FileSize(); /// @brief Will return true if a root node is there.
mData.resize(len + 1);
memset(&mData[0], '\0', len + 1);
stream->Read(&mData[0], 1, len);
mDoc = new pugi::xml_document();
pugi::xml_parse_result parse_result = mDoc->load_string(&mData[0], pugi::parse_full);
if (parse_result.status == pugi::status_ok) {
return true;
}
ASSIMP_LOG_DEBUG("Error while parse xml.", std::string(parse_result.description()), " @ ", parse_result.offset);
return false;
}
/// @brief Will return truem if a root node is there.
/// @return true in case of an existing root. /// @return true in case of an existing root.
bool hasRoot() const { bool hasRoot() const;
return nullptr != mDoc;
}
/// @brief Will return the document pointer, is nullptr if no xml-file was parsed. /// @brief Will return the document pointer, is nullptr if no xml-file was parsed.
/// @return The pointer showing to the document. /// @return The pointer showing to the document.
pugi::xml_document *getDocument() const { pugi::xml_document *getDocument() const;
return mDoc;
}
/// @brief Will return the root node, const version. /// @brief Will return the root node, const version.
/// @return The root node. /// @return The root node.
const TNodeType getRootNode() const { const TNodeType getRootNode() const;
static pugi::xml_node none;
if (nullptr == mDoc) {
return none;
}
return mDoc->root();
}
/// @brief Will return the root node, non-const version. /// @brief Will return the root node, non-const version.
/// @return The root node. /// @return The root node.
TNodeType getRootNode() { TNodeType getRootNode();
static pugi::xml_node none;
if (nullptr == mDoc) {
return none;
}
return mDoc->root();
}
/// @brief Will check if a node with the given name is in. /// @brief Will check if a node with the given name is in.
/// @param node [in] The node to look in. /// @param node [in] The node to look in.
/// @param name [in] The name of the child-node. /// @param name [in] The name of the child-node.
/// @return true, if node was found, false if not. /// @return true, if node was found, false if not.
static inline bool hasNode(XmlNode &node, const char *name) { static inline bool hasNode(XmlNode &node, const char *name);
pugi::xml_node child = node.find_child(find_node_by_name_predicate(name));
return !child.empty();
}
/// @brief Will check if an attribute is part of the XmlNode. /// @brief Will check if an attribute is part of the XmlNode.
/// @param xmlNode [in] The node to search in. /// @param xmlNode [in] The node to search in.
/// @param name [in} The attribute name to look for. /// @param name [in} The attribute name to look for.
/// @return true, if the was found, false if not. /// @return true, if the was found, false if not.
static inline bool hasAttribute(XmlNode &xmlNode, const char *name) { static inline bool hasAttribute(XmlNode &xmlNode, const char *name);
pugi::xml_attribute attr = xmlNode.attribute(name);
return !attr.empty();
}
/// @brief Will try to get an unsigned int attribute value. /// @brief Will try to get an unsigned int attribute value.
/// @param xmlNode [in] The node to search in. /// @param xmlNode [in] The node to search in.
/// @param name [in] The attribute name to look for. /// @param name [in] The attribute name to look for.
/// @param val [out] The unsigned int value from the attribute. /// @param val [out] The unsigned int value from the attribute.
/// @return true, if the node contains an attribute with the given name and if the value is an unsigned int. /// @return true, if the node contains an attribute with the given name and if the value is an unsigned int.
static inline bool getUIntAttribute(XmlNode &xmlNode, const char *name, unsigned int &val) { static inline bool getUIntAttribute(XmlNode &xmlNode, const char *name, unsigned int &val);
pugi::xml_attribute attr = xmlNode.attribute(name);
if (attr.empty()) {
return false;
}
val = attr.as_uint();
return true;
}
/// @brief Will try to get an int attribute value. /// @brief Will try to get an int attribute value.
/// @param xmlNode [in] The node to search in. /// @param xmlNode [in] The node to search in.
/// @param name [in] The attribute name to look for. /// @param name [in] The attribute name to look for.
/// @param val [out] The int value from the attribute. /// @param val [out] The int value from the attribute.
/// @return true, if the node contains an attribute with the given name and if the value is an int. /// @return true, if the node contains an attribute with the given name and if the value is an int.
static inline bool getIntAttribute(XmlNode &xmlNode, const char *name, int &val) { static inline bool getIntAttribute(XmlNode &xmlNode, const char *name, int &val);
pugi::xml_attribute attr = xmlNode.attribute(name);
if (attr.empty()) {
return false;
}
val = attr.as_int();
return true;
}
/// @brief Will try to get a real attribute value. /// @brief Will try to get a real attribute value.
/// @param xmlNode [in] The node to search in. /// @param xmlNode [in] The node to search in.
/// @param name [in] The attribute name to look for. /// @param name [in] The attribute name to look for.
/// @param val [out] The real value from the attribute. /// @param val [out] The real value from the attribute.
/// @return true, if the node contains an attribute with the given name and if the value is a real. /// @return true, if the node contains an attribute with the given name and if the value is a real.
static inline bool getRealAttribute(XmlNode &xmlNode, const char *name, ai_real &val) { static inline bool getRealAttribute(XmlNode &xmlNode, const char *name, ai_real &val);
pugi::xml_attribute attr = xmlNode.attribute(name);
if (attr.empty()) {
return false;
}
#ifdef ASSIMP_DOUBLE_PRECISION
val = attr.as_double();
#else
val = attr.as_float();
#endif
return true;
}
/// @brief Will try to get a float attribute value. /// @brief Will try to get a float attribute value.
/// @param xmlNode [in] The node to search in. /// @param xmlNode [in] The node to search in.
/// @param name [in] The attribute name to look for. /// @param name [in] The attribute name to look for.
/// @param val [out] The float value from the attribute. /// @param val [out] The float value from the attribute.
/// @return true, if the node contains an attribute with the given name and if the value is a float. /// @return true, if the node contains an attribute with the given name and if the value is a float.
static inline bool getFloatAttribute(XmlNode &xmlNode, const char *name, float &val) { static inline bool getFloatAttribute(XmlNode &xmlNode, const char *name, float &val);
pugi::xml_attribute attr = xmlNode.attribute(name);
if (attr.empty()) {
return false;
}
val = attr.as_float();
return true;
}
/// @brief Will try to get a double attribute value. /// @brief Will try to get a double attribute value.
/// @param xmlNode [in] The node to search in. /// @param xmlNode [in] The node to search in.
/// @param name [in] The attribute name to look for. /// @param name [in] The attribute name to look for.
/// @param val [out] The double value from the attribute. /// @param val [out] The double value from the attribute.
/// @return true, if the node contains an attribute with the given name and if the value is a double. /// @return true, if the node contains an attribute with the given name and if the value is a double.
static inline bool getDoubleAttribute(XmlNode &xmlNode, const char *name, double &val) { static inline bool getDoubleAttribute(XmlNode &xmlNode, const char *name, double &val);
pugi::xml_attribute attr = xmlNode.attribute(name);
if (attr.empty()) {
return false;
}
val = attr.as_double();
return true;
}
/// @brief Will try to get a std::string attribute value. /// @brief Will try to get a std::string attribute value.
/// @param xmlNode [in] The node to search in. /// @param xmlNode [in] The node to search in.
/// @param name [in] The attribute name to look for. /// @param name [in] The attribute name to look for.
/// @param val [out] The std::string value from the attribute. /// @param val [out] The std::string value from the attribute.
/// @return true, if the node contains an attribute with the given name and if the value is a std::string. /// @return true, if the node contains an attribute with the given name and if the value is a std::string.
static inline bool getStdStrAttribute(XmlNode &xmlNode, const char *name, std::string &val) { static inline bool getStdStrAttribute(XmlNode &xmlNode, const char *name, std::string &val);
pugi::xml_attribute attr = xmlNode.attribute(name);
if (attr.empty()) {
return false;
}
val = attr.as_string();
return true;
}
/// @brief Will try to get a bool attribute value. /// @brief Will try to get a bool attribute value.
/// @param xmlNode [in] The node to search in. /// @param xmlNode [in] The node to search in.
/// @param name [in] The attribute name to look for. /// @param name [in] The attribute name to look for.
/// @param val [out] The bool value from the attribute. /// @param val [out] The bool value from the attribute.
/// @return true, if the node contains an attribute with the given name and if the value is a bool. /// @return true, if the node contains an attribute with the given name and if the value is a bool.
static inline bool getBoolAttribute(XmlNode &xmlNode, const char *name, bool &val) { static inline bool getBoolAttribute(XmlNode &xmlNode, const char *name, bool &val);
pugi::xml_attribute attr = xmlNode.attribute(name);
if (attr.empty()) {
return false;
}
val = attr.as_bool();
return true;
}
/// @brief Will try to get the value of the node as a string. /// @brief Will try to get the value of the node as a string.
/// @param node [in] The node to search in. /// @param node [in] The node to search in.
/// @param text [out] The value as a text. /// @param text [out] The value as a text.
/// @return true, if the value can be read out. /// @return true, if the value can be read out.
static inline bool getValueAsString(XmlNode &node, std::string &text) { static inline bool getValueAsString(XmlNode &node, std::string &text);
text = std::string();
if (node.empty()) {
return false;
}
text = node.text().as_string();
return true;
}
/// @brief Will try to get the value of the node as a float. /// @brief Will try to get the value of the node as a float.
/// @param node [in] The node to search in. /// @param node [in] The node to search in.
/// @param text [out] The value as a float. /// @param text [out] The value as a float.
/// @return true, if the value can be read out. /// @return true, if the value can be read out.
static inline bool getValueAsFloat(XmlNode &node, ai_real &v) { static inline bool getValueAsFloat(XmlNode &node, ai_real &v);
if (node.empty()) {
return false;
}
v = node.text().as_float();
return true;
}
/// @brief Will try to get the value of the node as an integer. /// @brief Will try to get the value of the node as an integer.
/// @param node [in] The node to search in. /// @param node [in] The node to search in.
/// @param text [out] The value as a int. /// @param text [out] The value as a int.
/// @return true, if the value can be read out. /// @return true, if the value can be read out.
static inline bool getValueAsInt(XmlNode &node, int &v) { static inline bool getValueAsInt(XmlNode &node, int &v);
if (node.empty()) {
return false;
}
v = node.text().as_int();
return true;
}
/// @brief Will try to get the value of the node as an bool. /// @brief Will try to get the value of the node as an bool.
/// @param node [in] The node to search in. /// @param node [in] The node to search in.
/// @param text [out] The value as a bool. /// @param text [out] The value as a bool.
/// @return true, if the value can be read out. /// @return true, if the value can be read out.
static inline bool getValueAsBool(XmlNode& node, bool& v) static inline bool getValueAsBool(XmlNode &node, bool &v);
{
if (node.empty()) {
return false;
}
v = node.text().as_bool();
return true;
}
private: private:
pugi::xml_document *mDoc; pugi::xml_document *mDoc;
@ -395,6 +229,254 @@ private:
std::vector<char> mData; std::vector<char> mData;
}; };
template <class TNodeType>
inline TXmlParser<TNodeType>::TXmlParser() :
mDoc(nullptr),
mData() {
// empty
}
template <class TNodeType>
inline TXmlParser<TNodeType>::~TXmlParser() {
clear();
}
template <class TNodeType>
inline void TXmlParser<TNodeType>::clear() {
if (mData.empty()) {
if (mDoc) {
delete mDoc;
}
mDoc = nullptr;
return;
}
mData.clear();
delete mDoc;
mDoc = nullptr;
}
template <class TNodeType>
inline TNodeType *TXmlParser<TNodeType>::findNode(const std::string &name) {
if (name.empty()) {
return nullptr;
}
if (nullptr == mDoc) {
return nullptr;
}
find_node_by_name_predicate predicate(name);
mCurrent = mDoc->find_node(predicate);
if (mCurrent.empty()) {
return nullptr;
}
return &mCurrent;
}
template <class TNodeType>
bool TXmlParser<TNodeType>::hasNode(const std::string &name) {
return nullptr != findNode(name);
}
template <class TNodeType>
bool TXmlParser<TNodeType>::parse(IOStream *stream) {
if (hasRoot()) {
clear();
}
if (nullptr == stream) {
ASSIMP_LOG_DEBUG("Stream is nullptr.");
return false;
}
const size_t len = stream->FileSize();
mData.resize(len + 1);
memset(&mData[0], '\0', len + 1);
stream->Read(&mData[0], 1, len);
mDoc = new pugi::xml_document();
pugi::xml_parse_result parse_result = mDoc->load_string(&mData[0], pugi::parse_full);
if (parse_result.status == pugi::status_ok) {
return true;
}
ASSIMP_LOG_DEBUG("Error while parse xml.", std::string(parse_result.description()), " @ ", parse_result.offset);
return false;
}
template <class TNodeType>
bool TXmlParser<TNodeType>::hasRoot() const {
return nullptr != mDoc;
}
template <class TNodeType>
pugi::xml_document *TXmlParser<TNodeType>::getDocument() const {
return mDoc;
}
template <class TNodeType>
const TNodeType TXmlParser<TNodeType>::getRootNode() const {
static pugi::xml_node none;
if (nullptr == mDoc) {
return none;
}
return mDoc->root();
}
template <class TNodeType>
TNodeType TXmlParser<TNodeType>::getRootNode() {
static pugi::xml_node none;
if (nullptr == mDoc) {
return none;
}
return mDoc->root();
}
template <class TNodeType>
inline bool TXmlParser<TNodeType>::hasNode(XmlNode &node, const char *name) {
pugi::xml_node child = node.find_child(find_node_by_name_predicate(name));
return !child.empty();
}
template <class TNodeType>
inline bool TXmlParser<TNodeType>::hasAttribute(XmlNode &xmlNode, const char *name) {
pugi::xml_attribute attr = xmlNode.attribute(name);
return !attr.empty();
}
template <class TNodeType>
inline bool TXmlParser<TNodeType>::getUIntAttribute(XmlNode &xmlNode, const char *name, unsigned int &val) {
pugi::xml_attribute attr = xmlNode.attribute(name);
if (attr.empty()) {
return false;
}
val = attr.as_uint();
return true;
}
template <class TNodeType>
inline bool TXmlParser<TNodeType>::getIntAttribute(XmlNode &xmlNode, const char *name, int &val) {
pugi::xml_attribute attr = xmlNode.attribute(name);
if (attr.empty()) {
return false;
}
val = attr.as_int();
return true;
}
template <class TNodeType>
inline bool TXmlParser<TNodeType>::getRealAttribute(XmlNode &xmlNode, const char *name, ai_real &val) {
pugi::xml_attribute attr = xmlNode.attribute(name);
if (attr.empty()) {
return false;
}
#ifdef ASSIMP_DOUBLE_PRECISION
val = attr.as_double();
#else
val = attr.as_float();
#endif
return true;
}
template <class TNodeType>
inline bool TXmlParser<TNodeType>::getFloatAttribute(XmlNode &xmlNode, const char *name, float &val) {
pugi::xml_attribute attr = xmlNode.attribute(name);
if (attr.empty()) {
return false;
}
val = attr.as_float();
return true;
}
template <class TNodeType>
inline bool TXmlParser<TNodeType>::getDoubleAttribute(XmlNode &xmlNode, const char *name, double &val) {
pugi::xml_attribute attr = xmlNode.attribute(name);
if (attr.empty()) {
return false;
}
val = attr.as_double();
return true;
}
template <class TNodeType>
inline bool TXmlParser<TNodeType>::getStdStrAttribute(XmlNode &xmlNode, const char *name, std::string &val) {
pugi::xml_attribute attr = xmlNode.attribute(name);
if (attr.empty()) {
return false;
}
val = attr.as_string();
return true;
}
template <class TNodeType>
inline bool TXmlParser<TNodeType>::getBoolAttribute(XmlNode &xmlNode, const char *name, bool &val) {
pugi::xml_attribute attr = xmlNode.attribute(name);
if (attr.empty()) {
return false;
}
val = attr.as_bool();
return true;
}
template <class TNodeType>
inline bool TXmlParser<TNodeType>::getValueAsString(XmlNode &node, std::string &text) {
text = std::string();
if (node.empty()) {
return false;
}
text = node.text().as_string();
return true;
}
template <class TNodeType>
inline bool TXmlParser<TNodeType>::getValueAsFloat(XmlNode &node, ai_real &v) {
if (node.empty()) {
return false;
}
v = node.text().as_float();
return true;
}
template <class TNodeType>
inline bool TXmlParser<TNodeType>::getValueAsInt(XmlNode &node, int &v) {
if (node.empty()) {
return false;
}
v = node.text().as_int();
return true;
}
template <class TNodeType>
inline bool TXmlParser<TNodeType>::getValueAsBool(XmlNode &node, bool &v) {
if (node.empty()) {
return false;
}
v = node.text().as_bool();
return true;
}
using XmlParser = TXmlParser<pugi::xml_node>; using XmlParser = TXmlParser<pugi::xml_node>;
/// @brief This class declares an iterator to loop through all children of the root node. /// @brief This class declares an iterator to loop through all children of the root node.
@ -419,10 +501,8 @@ public:
} }
} }
/// @brief The class destructor. /// @brief The class destructor, default implementation.
~XmlNodeIterator() { ~XmlNodeIterator() = default;
// empty
}
/// @brief Will iterate through all children in pre-order iteration. /// @brief Will iterate through all children in pre-order iteration.
/// @param node [in] The nod to iterate through. /// @param node [in] The nod to iterate through.

View File

@ -0,0 +1,196 @@
<?xml version="1.0" encoding="utf-8"?>
<COLLADA xmlns="http://www.collada.org/2005/11/COLLADASchema" version="1.4.1" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<asset>
<contributor>
<author>Blender User</author>
<authoring_tool>Blender 2.80.40 commit date:2019-01-07, commit time:23:37, hash:91a155833e59</authoring_tool>
</contributor>
<created>2019-01-08T17:44:11</created>
<modified>2019-01-08T17:44:11</modified>
<unit name="meter" meter="1"/>
<up_axis>Z_UP</up_axis>
</asset>
<library_effects>
<effect id="Material-effect">
<profile_COMMON>
<technique sid="common">
<lambert>
<diffuse>
<color sid="diffuse">0.8 0.8 0.8 1</color>
</diffuse>
<specular>
<color sid="specular">0 0.5 0 1</color>
</specular>
</lambert>
</technique>
</profile_COMMON>
</effect>
</library_effects>
<library_images/>
<library_materials>
<material id="Material-material" name="Material">
<instance_effect url="#Material-effect"/>
</material>
</library_materials>
<library_geometries>
<geometry id="Cube-mesh" name="Cube">
<mesh>
<source id="Cube-mesh-positions">
<float_array id="Cube-mesh-positions-array" count="24">1 1 1 1 1 -1 1 -1 1 1 -1 -1 -1 1 1 -1 1 -1 -1 -1 1 -1 -1 -1</float_array>
<technique_common>
<accessor source="#Cube-mesh-positions-array" count="8" stride="3">
<param name="X" type="float"/>
<param name="Y" type="float"/>
<param name="Z" type="float"/>
</accessor>
</technique_common>
</source>
<source id="Cube-mesh-normals">
<float_array id="Cube-mesh-normals-array" count="18">0 0 1 0 -1 0 -1 0 0 0 0 -1 1 0 0 0 1 0</float_array>
<technique_common>
<accessor source="#Cube-mesh-normals-array" count="6" stride="3">
<param name="X" type="float"/>
<param name="Y" type="float"/>
<param name="Z" type="float"/>
</accessor>
</technique_common>
</source>
<source id="Cube-mesh-map-0">
<float_array id="Cube-mesh-map-0-array" count="72">0.625 0 0.375 0.25 0.375 0 0.625 0.25 0.375 0.5 0.375 0.25 0.625 0.5 0.375 0.75 0.375 0.5 0.625 0.75 0.375 1 0.375 0.75 0.375 0.5 0.125 0.75 0.125 0.5 0.875 0.5 0.625 0.75 0.625 0.5 0.625 0 0.625 0.25 0.375 0.25 0.625 0.25 0.625 0.5 0.375 0.5 0.625 0.5 0.625 0.75 0.375 0.75 0.625 0.75 0.625 1 0.375 1 0.375 0.5 0.375 0.75 0.125 0.75 0.875 0.5 0.875 0.75 0.625 0.75</float_array>
<technique_common>
<accessor source="#Cube-mesh-map-0-array" count="36" stride="2">
<param name="S" type="float"/>
<param name="T" type="float"/>
</accessor>
</technique_common>
</source>
<vertices id="Cube-mesh-vertices">
<input semantic="POSITION" source="#Cube-mesh-positions"/>
</vertices>
<polylist material="Material-material" count="12">
<input semantic="VERTEX" source="#Cube-mesh-vertices" offset="0"/>
<input semantic="NORMAL" source="#Cube-mesh-normals" offset="1"/>
<input semantic="TEXCOORD" source="#Cube-mesh-map-0" offset="2" set="1"/>
<vcount>3 3 3 3 3 3 3 3 3 3 3 3 </vcount>
<p>4 0 0 2 0 1 0 0 2 2 1 3 7 1 4 3 1 5 6 2 6 5 2 7 7 2 8 1 3 9 7 3 10 5 3 11 0 4 12 3 4 13 1 4 14 4 5 15 1 5 16 5 5 17 4 0 18 6 0 19 2 0 20 2 1 21 6 1 22 7 1 23 6 2 24 4 2 25 5 2 26 1 3 27 3 3 28 7 3 29 0 4 30 2 4 31 3 4 32 4 5 33 0 5 34 1 5 35</p>
</polylist>
</mesh>
</geometry>
</library_geometries>
<library_controllers>
<controller id="Armature_Cube-skin" name="Armature">
<skin source="#Cube-mesh">
<bind_shape_matrix>1 0 0 -1 0 1 0 1 0 0 1 1 0 0 0 1</bind_shape_matrix>
<source id="Armature_Cube-skin-joints">
<Name_array id="Armature_Cube-skin-joints-array" count="1">Bone</Name_array>
<technique_common>
<accessor source="#Armature_Cube-skin-joints-array" count="1" stride="1">
<param name="JOINT" type="name"/>
</accessor>
</technique_common>
</source>
<source id="Armature_Cube-skin-bind_poses">
<float_array id="Armature_Cube-skin-bind_poses-array" count="16">0.7886752 0.2113248 0.5773504 -0.5773504 -0.5773503 0.5773503 0.5773503 1.154701 -0.2113249 -0.7886752 0.5773503 -0.5773502 0 0 0 1</float_array>
<technique_common>
<accessor source="#Armature_Cube-skin-bind_poses-array" count="1" stride="16">
<param name="TRANSFORM" type="float4x4"/>
</accessor>
</technique_common>
</source>
<source id="Armature_Cube-skin-weights">
<float_array id="Armature_Cube-skin-weights-array" count="8">1 1 1 1 1 1 1 1</float_array>
<technique_common>
<accessor source="#Armature_Cube-skin-weights-array" count="8" stride="1">
<param name="WEIGHT" type="float"/>
</accessor>
</technique_common>
</source>
<joints>
<input semantic="JOINT" source="#Armature_Cube-skin-joints"/>
<input semantic="INV_BIND_MATRIX" source="#Armature_Cube-skin-bind_poses"/>
</joints>
<vertex_weights count="8">
<input semantic="JOINT" source="#Armature_Cube-skin-joints" offset="0"/>
<input semantic="WEIGHT" source="#Armature_Cube-skin-weights" offset="1"/>
<vcount>1 1 1 1 1 1 1 1 </vcount>
<v>0 0 0 1 0 2 0 3 0 4 0 5 0 6 0 7</v>
</vertex_weights>
</skin>
</controller>
</library_controllers>
<library_animations>
<animation id="action_container-Armature" name="Armature">
<animation id="Armature_ArmatureAction_transform" name="Armature">
<source id="Armature_ArmatureAction_transform-input">
<float_array id="Armature_ArmatureAction_transform-input-array" count="40">0.04166662 0.08333331 0.125 0.1666666 0.2083333 0.25 0.2916666 0.3333333 0.375 0.4166666 0.4583333 0.5 0.5416667 0.5833333 0.625 0.6666667 0.7083333 0.75 0.7916667 0.8333333 0.875 0.9166667 0.9583333 1 1.041667 1.083333 1.125 1.166667 1.208333 1.25 1.291667 1.333333 1.375 1.416667 1.458333 1.5 1.541667 1.583333 1.625 1.666667</float_array>
<technique_common>
<accessor source="#Armature_ArmatureAction_transform-input-array" count="40" stride="1">
<param name="TIME" type="float"/>
</accessor>
</technique_common>
</source>
<source id="Armature_ArmatureAction_transform-output">
<float_array id="Armature_ArmatureAction_transform-output-array" count="640">1 0 0 1 0 1 0 -1 0 0 1 0 0 0 0 1 0.9999878 3.10816e-5 0.004935208 1 0 0.9999802 -0.006297799 -1 -0.004935306 0.006297722 0.999968 0 0 0 0 1 0.999819 4.61727e-4 0.01901668 1 0 0.9997054 -0.02427293 -1 -0.01902229 0.02426853 0.9995245 0 0 0 0 1 0.9991519 0.002163141 0.04111904 1 0 0.9986191 -0.05253414 -1 -0.04117589 0.05248959 0.9977722 0 0 0 0 1 0.9975264 0.006301912 0.07000974 1 0 0.9959731 -0.08965231 -1 -0.0702928 0.08943056 0.9935095 0 0 0 0 1 0.9944467 0.01411698 0.1042901 1 0 0.9909625 -0.1341392 -1 -0.1052413 0.1333943 0.9854594 0 0 0 0 1 0.9894527 0.02671701 0.1423712 1 0 0.9828442 -0.184438 -1 -0.1448563 0.1824927 0.9724778 0 0 0 0 1 0.9821799 0.04490547 0.1825 1 0 0.9710366 -0.2389307 -1 -0.1879434 0.234673 0.9537326 0 0 0 0 1 0.9724072 0.06904543 0.2228386 1 0 0.9551992 -0.2959637 -1 -0.2332902 0.2877972 0.9288425 0 0 0 0 1 0.9600915 0.09897761 0.261587 1 0 0.9352878 -0.3538882 -1 -0.2796861 0.339765 0.8979618 0 0 0 0 1 0.9453882 0.1340003 0.2971281 1 0 0.9115852 -0.4111113 -1 -0.3259466 0.3886598 0.8618018 0 0 0 0 1 0.9286572 0.1729132 0.328172 1 0 0.8847058 -0.4661497 -1 -0.3709391 0.4328933 0.8215885 0 0 0 0 1 0.9104556 0.2141147 0.3538722 1 0 0.8555763 -0.5176768 -1 -0.4136069 0.4713217 0.7789642 0 0 0 0 1 0.8915175 0.2557371 0.3738919 1 0 0.8253933 -0.5645581 -1 -0.4529863 0.5033134 0.7358525 0 0 0 0 1 0.8727233 0.2957927 0.388408 1 0 0.7955672 -0.6058654 -1 -0.4882152 0.5287529 0.6943099 0 0 0 0 1 0.8550603 0.332307 0.3980502 1 0 0.7676533 -0.6408653 -1 -0.5185286 0.5479785 0.6563899 0 0 0 0 1 0.8395769 0.3634188 0.4037789 1 0 0.7432778 -0.6689829 -1 -0.5432408 0.5616626 0.6240388 0 0 0 0 1 0.8273312 0.3874339 0.4067161 1 0 0.7240622 -0.6897347 -1 -0.5617144 0.5706391 0.5990393 0 0 0 0 1 0.8193359 0.4028329 0.4079393 1 0 0.7115462 -0.7026393 -1 -0.5733138 0.5756976 0.5829953 0 0 0 0 1 0.8164964 0.4082482 0.4082486 1 7.75722e-8 0.707107 -0.7071065 -1 -0.5773504 0.57735 0.5773503 0 0 0 0 1 0.8190646 0.4033515 0.4079717 1 7.78161e-8 0.7111219 -0.7030687 -1 -0.5737014 0.5758587 0.5824547 0 0 0 0 1 0.8263245 0.3893851 0.4068995 1 7.85059e-8 0.7224849 -0.6913868 -1 -0.5631944 0.5713098 0.5970069 0 0 0 0 1 0.8375081 0.3675125 0.4043696 1 7.95684e-8 0.7400277 -0.6725764 -1 -0.5464249 0.5632883 0.6197791 0 0 0 0 1 0.8517552 0.3390183 0.3994742 1 8.0922e-8 0.7624427 -0.6470557 -1 -0.5239399 0.5511332 0.6494145 0 0 0 0 1 0.8681612 0.3053284 0.3912425 1 8.24806e-8 0.7883466 -0.6152314 -1 -0.4962822 0.5341201 0.6844119 0 0 0 0 1 0.8858209 0.2680094 0.3788038 1 8.41584e-8 0.8163394 -0.5775725 -1 -0.4640273 0.5116258 0.7231305 0 0 0 0 1 0.9038687 0.2287352 0.3615268 1 8.58731e-8 0.8450637 -0.5346656 -1 -0.42781 0.4832675 0.7638266 0 0 0 0 1 0.9215156 0.1892192 0.339124 1 8.75496e-8 0.8732626 -0.4872499 -1 -0.3883413 0.4490085 0.8047251 0 0 0 0 1 0.9380813 0.1511175 0.3117163 1 8.91235e-8 0.899834 -0.4362323 -1 -0.3464153 0.4092214 0.8441175 0 0 0 0 1 0.9530206 0.1159168 0.2798482 1 9.05428e-8 0.9238796 -0.3826832 -1 -0.3029055 0.3647051 0.8804763 0 0 0 0 1 0.965943 0.08482374 0.2444564 1 9.17705e-8 0.9447417 -0.3278156 -1 -0.2587547 0.3166512 0.9125667 0 0 0 0 1 0.9766233 0.05867312 0.2067956 1 9.27852e-8 0.9620277 -0.2729518 -1 -0.2149581 0.2665711 0.9395387 0 0 0 0 1 0.9850019 0.03787052 0.1683363 1 9.35812e-8 0.975616 -0.2194843 -1 -0.1725436 0.2161924 0.9609836 0 0 0 0 1 0.991176 0.02237916 0.1306496 1 9.41678e-8 0.9856446 -0.1688333 -1 -0.1325524 0.1673435 0.9769473 0 0 0 0 1 0.9953793 0.01175384 0.09529842 1 9.45671e-8 0.9924796 -0.1224106 -1 -0.09602053 0.121845 0.9878936 0 0 0 0 1 0.997952 0.005218936 0.06375288 1 9.48115e-8 0.996666 -0.08159051 -1 -0.06396614 0.08142342 0.9946249 0 0 0 0 1 0.9993011 0.001782816 0.03733916 1 9.49397e-8 0.998862 -0.04769476 -1 -0.0373817 0.04766143 0.9981638 0 0 0 0 1 0.9998515 3.78837e-4 0.01722835 1 9.4992e-8 0.9997582 -0.02198936 -1 -0.01723252 0.0219861 0.9996098 0 0 0 0 1 0.99999 2.53135e-5 0.004462156 1 9.50052e-8 0.9999838 -0.00569412 -1 -0.004462227 0.005694063 0.9999738 0 0 0 0 1 1 0 0 2 0 1 0 -1 0 0 1 0 0 0 0 1</float_array>
<technique_common>
<accessor source="#Armature_ArmatureAction_transform-output-array" count="40" stride="16">
<param name="TRANSFORM" type="float4x4"/>
</accessor>
</technique_common>
</source>
<source id="Armature_ArmatureAction_transform-interpolation">
<Name_array id="Armature_ArmatureAction_transform-interpolation-array" count="40">LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR LINEAR</Name_array>
<technique_common>
<accessor source="#Armature_ArmatureAction_transform-interpolation-array" count="40" stride="1">
<param name="INTERPOLATION" type="name"/>
</accessor>
</technique_common>
</source>
<sampler id="Armature_ArmatureAction_transform-sampler">
<input semantic="INPUT" source="#Armature_ArmatureAction_transform-input"/>
<input semantic="OUTPUT" source="#Armature_ArmatureAction_transform-output"/>
<input semantic="INTERPOLATION" source="#Armature_ArmatureAction_transform-interpolation"/>
</sampler>
<channel source="#Armature_ArmatureAction_transform-sampler" target="Armature_Bone/transform"/>
</animation>
</animation>
</library_animations>
<library_visual_scenes>
<visual_scene id="Scene" name="Scene">
<node id="Armature" name="Armature" type="NODE">
<matrix sid="transform">1 0 0 1 0 1 0 -1 0 0 1 0 0 0 0 1</matrix>
<node id="Armature_Bone" name="Bone" sid="Bone" type="JOINT">
<matrix sid="transform">0.7886751 -0.5773503 -0.211325 0 0.2113248 0.5773503 -0.7886751 0 0.5773503 0.5773503 0.5773502 0 0 0 0 1</matrix>
<extra>
<technique profile="blender">
<layer sid="layer" type="string">0</layer>
<roll sid="roll" type="float">-0.5235989</roll>
<tip_x sid="tip_x" type="float">-2</tip_x>
<tip_y sid="tip_y" type="float">2</tip_y>
<tip_z sid="tip_z" type="float">2</tip_z>
</technique>
</extra>
</node>
<node id="Cube" name="Cube" type="NODE">
<translate sid="location">0 0 0</translate>
<rotate sid="rotationZ">0 0 1 0</rotate>
<rotate sid="rotationY">0 1 0 0</rotate>
<rotate sid="rotationX">1 0 0 0</rotate>
<scale sid="scale">1 1 1</scale>
<instance_controller url="#Armature_Cube-skin">
<skeleton>#Armature_Bone</skeleton>
<bind_material>
<technique_common>
<instance_material symbol="Material-material" target="#Material-material">
<bind_vertex_input semantic="UVMap" input_semantic="TEXCOORD" input_set="0"/>
</instance_material>
</technique_common>
</bind_material>
</instance_controller>
</node>
</node>
</visual_scene>
</library_visual_scenes>
<scene>
<instance_visual_scene url="#Scene"/>
</scene>
</COLLADA>

View File

@ -69,31 +69,44 @@ public:
virtual bool importerTest() final { virtual bool importerTest() final {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck.dae", aiProcess_ValidateDataStructure); {
if (scene == nullptr) const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/duck.dae", aiProcess_ValidateDataStructure);
return false; if (scene == nullptr)
return false;
// Expected number of items // Expected number of items
EXPECT_EQ(scene->mNumMeshes, 1u); EXPECT_EQ(scene->mNumMeshes, 1u);
EXPECT_EQ(scene->mNumMaterials, 1u); EXPECT_EQ(scene->mNumMaterials, 1u);
EXPECT_EQ(scene->mNumAnimations, 0u); EXPECT_EQ(scene->mNumAnimations, 0u);
EXPECT_EQ(scene->mNumTextures, 0u); EXPECT_EQ(scene->mNumTextures, 0u);
EXPECT_EQ(scene->mNumLights, 1u); EXPECT_EQ(scene->mNumLights, 1u);
EXPECT_EQ(scene->mNumCameras, 1u); EXPECT_EQ(scene->mNumCameras, 1u);
// Expected common metadata // Expected common metadata
aiString value; aiString value;
EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT, value)) << "No importer format metadata"; EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT, value)) << "No importer format metadata";
EXPECT_STREQ("Collada Importer", value.C_Str()); EXPECT_STREQ("Collada Importer", value.C_Str());
EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT_VERSION, value)) << "No format version metadata"; EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_FORMAT_VERSION, value)) << "No format version metadata";
EXPECT_STREQ("1.4.1", value.C_Str()); EXPECT_STREQ("1.4.1", value.C_Str());
EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_GENERATOR, value)) << "No generator metadata"; EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_GENERATOR, value)) << "No generator metadata";
EXPECT_EQ(strncmp(value.C_Str(), "Maya 8.0", 8), 0) << "AI_METADATA_SOURCE_GENERATOR was: " << value.C_Str(); EXPECT_EQ(strncmp(value.C_Str(), "Maya 8.0", 8), 0) << "AI_METADATA_SOURCE_GENERATOR was: " << value.C_Str();
EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_COPYRIGHT, value)) << "No copyright metadata"; EXPECT_TRUE(scene->mMetaData->Get(AI_METADATA_SOURCE_COPYRIGHT, value)) << "No copyright metadata";
EXPECT_EQ(strncmp(value.C_Str(), "Copyright 2006", 14), 0) << "AI_METADATA_SOURCE_COPYRIGHT was: " << value.C_Str(); EXPECT_EQ(strncmp(value.C_Str(), "Copyright 2006", 14), 0) << "AI_METADATA_SOURCE_COPYRIGHT was: " << value.C_Str();
}
{
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/Collada/box_nested_animation.dae", aiProcess_ValidateDataStructure);
if (scene == nullptr)
return false;
// Expect only one animation with the correct name
EXPECT_EQ(scene->mNumAnimations, 1u);
EXPECT_EQ(std::string(scene->mAnimations[0]->mName.C_Str()), std::string("Armature"));
}
return true; return true;
} }

View File

@ -40,6 +40,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/ */
#include "AbstractImportExportBase.h" #include "AbstractImportExportBase.h"
#include <assimp/scene.h>
#include "UnitTestPCH.h" #include "UnitTestPCH.h"
#include <assimp/Importer.hpp> #include <assimp/Importer.hpp>
@ -51,11 +53,12 @@ public:
bool importerTest() override { bool importerTest() override {
Assimp::Importer importer; Assimp::Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/OpenGEX/Example.ogex", 0); const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/OpenGEX/Example.ogex", 0);
EXPECT_EQ(1u, scene->mNumMeshes);
return nullptr != scene; return nullptr != scene;
} }
}; };
TEST_F(utOpenGEXImportExport, importLWSFromFileTest) { TEST_F(utOpenGEXImportExport, importOpenGexFromFileTest) {
EXPECT_TRUE(importerTest()); EXPECT_TRUE(importerTest());
} }