Compare commits

..

16 Commits

Author SHA1 Message Date
Kim Kulling
30c4784619 Use constexpr 2025-11-24 20:13:43 +01:00
Kim Kulling
f7d2de1efc Replace string copy by using pure iterators. 2025-11-23 20:16:40 +01:00
Kim Kulling
74a72a20e2 SIB: Fix unittests 2025-11-16 19:54:45 +01:00
Kim Kulling
07f24a7e93 Update glTF2Exporter.cpp 2025-11-16 17:19:49 +01:00
Kim Kulling
122884557e Update glTF2AssetWriter.h 2025-11-16 17:19:29 +01:00
Kim Kulling
18d84b5d20 Update glTFAsset.h 2025-11-16 17:18:45 +01:00
Kim Kulling
2b3dfb9164 Merge branch 'master' into bugfix/fix_linkage_no_importers_issue-5971 2025-11-16 17:07:58 +01:00
Kim Kulling
05a4fb57f1 Reorganize code top prevent security warning. (#6395)
* Reorganize code to prevent security warning.
2025-11-15 12:16:56 +01:00
John Curley
a53807a02a Added static cast for conversion from uLong to unsigned int for compiler error (#6393)
Co-authored-by: Kim Kulling <kimkulling@users.noreply.github.com>
2025-11-15 08:53:24 +01:00
Kim Kulling
1cc7f2ba74 Fix the doxygen documentation from public headers (#6394)
* Add documentation comments to DeboneProcess.h
2025-11-14 22:05:08 +01:00
Kim Kulling
e98ec7b2d3 Refactor string checks and variable declarations (#6392)
* Refactor string checks and variable declarations

* Change string check from contains to find

* Fix syntax error in mesh node creation loop
2025-11-14 00:18:35 +01:00
Kim Kulling
9143651e2e Remove commented out GLTF importer guard 2025-11-11 15:36:17 +01:00
Kim Kulling
bec3e1a089 Refactor glTFCommon namespace structure
Refactor namespace declarations for consistency.
2025-11-11 15:35:25 +01:00
Kim Kulling
0e6af01232 Remove unused preprocessor directives in glTF2Exporter 2025-11-11 15:33:42 +01:00
Kim Kulling
c54522f3c1 Merge branch 'master' into bugfix/fix_linkage_no_importers_issue-5971 2025-11-11 09:32:27 +01:00
Kim Kulling
5e084cd1e8 Fix linkage 2025-11-10 21:36:40 +01:00
40 changed files with 497 additions and 428 deletions

View File

@@ -1,7 +1,7 @@
FROM gcc:1.5.1.0
RUN apt-get update \
apt-get install -y ninja-build cmake zlib1g-dev
apt-get install --no-install-recommends -y ninja-build cmake zlib1g-dev
WORKDIR /app

View File

@@ -178,7 +178,7 @@ void CopyTexture(aiMaterial &mat, Texture &texture, aiTextureType type) {
mat.AddProperty<ai_real>(&texture.mTextureBlend, 1, AI_MATKEY_TEXBLEND(type, 0));
// Setup the texture mapping mode
int mapMode = static_cast<int>(texture.mMapMode);
auto mapMode = static_cast<int>(texture.mMapMode);
mat.AddProperty<int>(&mapMode, 1, AI_MATKEY_MAPPINGMODE_U(type, 0));
mat.AddProperty<int>(&mapMode, 1, AI_MATKEY_MAPPINGMODE_V(type, 0));
@@ -333,7 +333,8 @@ void Discreet3DSImporter::ConvertMeshes(aiScene *pcOut) {
for (auto i = mScene->mMeshes.begin(); i != mScene->mMeshes.end(); ++i) {
std::unique_ptr<std::vector<unsigned int>[]> aiSplit(new std::vector<unsigned int>[mScene->mMaterials.size()]);
name.length = ASSIMP_itoa10(name.data, num++);
name.length = ASSIMP_itoa10(name.data, num);
++num;
unsigned int iNum = 0;
for (std::vector<unsigned int>::const_iterator a = (*i).mFaceMaterials.begin();
@@ -477,7 +478,7 @@ void Discreet3DSImporter::AddNodeToGraph(aiScene *pcSOut, aiNode *pcOut, D3DS::N
// Setup the name of the node
// First instance keeps its name otherwise something might break, all others will be postfixed with their instance number
if (pcIn->mInstanceNumber > 1) {
char tmp[12];
char tmp[12] = {'\0'};
ASSIMP_itoa10(tmp, pcIn->mInstanceNumber);
std::string tempStr = pcIn->mName + "_inst_";
tempStr += tmp;
@@ -704,7 +705,8 @@ void Discreet3DSImporter::GenerateNodeGraph(aiScene *pcOut) {
// Build dummy nodes for all meshes
unsigned int a = 0;
for (unsigned int i = 0; i < pcOut->mNumMeshes; ++i, ++a) {
aiNode *pcNode = pcOut->mRootNode->mChildren[a] = new aiNode();
pcOut->mRootNode->mChildren[a] = new aiNode();
auto *pcNode = pcOut->mRootNode->mChildren[a];
pcNode->mParent = pcOut->mRootNode;
pcNode->mMeshes = new unsigned int[1];
pcNode->mMeshes[0] = i;

View File

@@ -47,8 +47,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_FBX_EXPORTER
namespace Assimp {
namespace FBX {
namespace Assimp::FBX {
static constexpr size_t NumNullRecords = 25;
@@ -84,8 +83,7 @@ enum TransformInheritance {
TransformInheritance_MAX // end-of-enum sentinel
};
} // namespace FBX
} // namespace Assimp
} // namespace Assimp::FBX
#endif // ASSIMP_BUILD_NO_FBX_EXPORTER

View File

@@ -50,11 +50,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <string>
#include <cstring>
#ifndef ASSIMP_BUILD_NO_FBX_IMPORTER
namespace Assimp {
namespace FBX {
namespace Util {
namespace Assimp::FBX::Util {
// ------------------------------------------------------------------------------------------------
const char* TokenTypeString(TokenType t)
@@ -233,8 +229,5 @@ std::string EncodeBase64(const char* data, size_t length)
return encoded_string;
}
} // !Util
} // !FBX
} // !Assimp
} // namespace Assimp::FBX::Util
#endif

View File

@@ -49,10 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "FBXTokenizer.h"
#include <stdint.h>
namespace Assimp {
namespace FBX {
namespace Util {
namespace Assimp::FBX::Util {
/** helper for std::for_each to delete all heap-allocated items in a container */
template<typename T>
@@ -73,12 +70,9 @@ struct destructor_fun {
}
};
/** Get a string representation for a #TokenType. */
const char* TokenTypeString(TokenType t);
/** Format log/error messages using a given offset in the source binary file
*
* @param offset offset within the file
@@ -129,8 +123,6 @@ char EncodeBase64(char byte);
* @return base64-encoded string*/
std::string EncodeBase64(const char* data, size_t length);
}
}
}
#endif // ! INCLUDED_AI_FBX_UTIL_H

View File

@@ -80,7 +80,7 @@ ObjFileParser::ObjFileParser(IOStreamBuffer<char> &streamBuffer, const std::stri
m_buffer(),
m_pIO(io),
m_progress(progress),
m_originalObjFileName(originalObjFileName) {
m_originalObjFileName(originalObjFileName) {
std::fill_n(m_buffer, Buffersize, '\0');
// Create the model instance to store all the data
@@ -140,9 +140,11 @@ void ObjFileParser::parseFile(IOStreamBuffer<char> &streamBuffer) {
if (insideCstype) {
switch (*m_DataIt) {
case 'e': {
std::string name;
getNameNoSpace(m_DataIt, m_DataItEnd, name);
insideCstype = name != "end";
char *name{nullptr};
size_t len{0};
getNameNoSpace(m_DataIt, m_DataItEnd, &name, len);
//insideCstype = name != "end";
insideCstype = strncmp(name, "end", len) == 0;
} break;
}
goto pf_skip_line;
@@ -198,32 +200,37 @@ void ObjFileParser::parseFile(IOStreamBuffer<char> &streamBuffer) {
case 'u': // Parse a material desc. setter
{
std::string name;
//std::string name;
char *name{nullptr};
size_t len{ 0 };
getNameNoSpace(m_DataIt, m_DataItEnd, &name, len);
getNameNoSpace(m_DataIt, m_DataItEnd, name);
//size_t nextSpace = name.find(' ');
//if (nextSpace != std::string::npos)
// name = name.substr(0, nextSpace);
size_t nextSpace = name.find(' ');
if (nextSpace != std::string::npos)
name = name.substr(0, nextSpace);
if (name == "usemtl") {
//if (name == "usemtl") {
if (strncmp(name, "usemtl", len) == 0) {
getMaterialDesc();
}
} break;
case 'm': // Parse a material library or merging group ('mg')
{
std::string name;
// std::string name;
char *name{nullptr};
size_t len{ 0 };
getNameNoSpace(m_DataIt, m_DataItEnd, &name, len);
getNameNoSpace(m_DataIt, m_DataItEnd, name);
//size_t nextSpace = name.find(' ');
//if (nextSpace != std::string::npos)
// name = name.substr(0, nextSpace);
size_t nextSpace = name.find(' ');
if (nextSpace != std::string::npos)
name = name.substr(0, nextSpace);
if (name == "mg")
if (strncmp(name, "mg", len) == 0)
//if (name == "mg")
getGroupNumberAndResolution();
else if (name == "mtllib")
//else if (name == "mtllib")
else if (strncmp(name, "mtllib", len) == 0)
getMaterialLib();
else
goto pf_skip_line;
@@ -246,9 +253,12 @@ void ObjFileParser::parseFile(IOStreamBuffer<char> &streamBuffer) {
case 'c': // handle cstype section start
{
std::string name;
getNameNoSpace(m_DataIt, m_DataItEnd, name);
insideCstype = name == "cstype";
//std::string name;
char *name{nullptr};
size_t len{0};
getNameNoSpace(m_DataIt, m_DataItEnd, &name, len);
//insideCstype = name == "cstype";
insideCstype = strncmp(name, "cstype", len) == 0;
goto pf_skip_line;
}

View File

@@ -177,8 +177,9 @@ inline char_t getName(char_t it, char_t end, std::string &name) {
* @return Current-iterator with new position
*/
template <class char_t>
inline char_t getNameNoSpace(char_t it, char_t end, std::string &name) {
name = "";
inline char_t getNameNoSpace(char_t it, char_t end, char **name, size_t &len) {
*name = nullptr;
len = 0;
if (isEndOfBuffer(it, end)) {
return end;
}
@@ -186,22 +187,23 @@ inline char_t getNameNoSpace(char_t it, char_t end, std::string &name) {
char *pStart = &(*it);
while (!isEndOfBuffer(it, end) && !IsLineEnd(*it) && !IsSpaceOrNewLine(*it)) {
++it;
++len;
}
while (isEndOfBuffer(it, end) || IsLineEnd(*it) || IsSpaceOrNewLine(*it)) {
--it;
--len;
}
++it;
++len;
// Get name
// if there is no name, and the previous char is a separator, come back to start
while (&(*it) < pStart) {
++it;
++len;
}
std::string strName(pStart, &(*it));
if (!strName.empty()) {
name = strName;
}
*name = pStart;
return it;
}
@@ -239,7 +241,7 @@ inline char_t CopyNextWord(char_t it, char_t end, char *pBuffer, size_t length)
*/
template <class char_t>
inline char_t getFloat(char_t it, char_t end, ai_real &value) {
static const size_t BUFFERSIZE = 1024;
static constexpr size_t BUFFERSIZE = 1024;
char buffer[BUFFERSIZE] = {};
it = CopyNextWord<char_t>(it, end, buffer, BUFFERSIZE);
value = (ai_real)fast_atof(buffer);

View File

@@ -49,8 +49,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GLTFASSET_H_INC
#define GLTFASSET_H_INC
#if !defined(ASSIMP_BUILD_NO_GLTF_IMPORTER) && !defined(ASSIMP_BUILD_NO_GLTF1_IMPORTER)
#include "AssetLib/glTFCommon/glTFCommon.h"
#include <assimp/Exceptional.h>
#include <list>
@@ -1008,6 +1006,4 @@ private:
// Include the implementation of the methods
#include "glTFAsset.inl"
#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
#endif // GLTFASSET_H_INC

View File

@@ -49,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GLTFASSETWRITER_H_INC
#define GLTFASSETWRITER_H_INC
#if !defined(ASSIMP_BUILD_NO_GLTF_IMPORTER) && !defined(ASSIMP_BUILD_NO_GLTF1_IMPORTER)
//#if !defined(ASSIMP_BUILD_NO_GLTF_IMPORTER) && !defined(ASSIMP_BUILD_NO_GLTF1_IMPORTER)
#include "glTFAsset.h"
@@ -63,16 +63,6 @@ class AssetWriter
template<class T>
friend void WriteLazyDict(LazyDict<T>& d, AssetWriter& w);
private:
void WriteBinaryData(IOStream* outfile, size_t sceneLength);
void WriteMetadata();
void WriteExtensionsUsed();
template<class T>
void WriteObjects(LazyDict<T>& d);
public:
Document mDoc;
Asset& mAsset;
@@ -80,9 +70,19 @@ public:
MemoryPoolAllocator<>& mAl;
AssetWriter(Asset& asset);
~AssetWriter() = default;
void WriteFile(const char* path);
void WriteGLBFile(const char* path);
private:
void WriteBinaryData(IOStream* outfile, size_t sceneLength);
void WriteMetadata();
void WriteExtensionsUsed();
template<class T>
void WriteObjects(LazyDict<T>& d);
};
}
@@ -90,6 +90,6 @@ public:
// Include the implementation of the methods
#include "glTFAssetWriter.inl"
#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
//#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
#endif // GLTFASSETWRITER_H_INC

View File

@@ -42,6 +42,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef ASSIMP_BUILD_NO_GLTF_EXPORTER
#include "AssetLib/glTF/glTFExporter.h"
#include "AssetLib/glTF/glTFAsset.h"
#include "AssetLib/glTF/glTFAssetWriter.h"
#include "PostProcessing/SplitLargeMeshes.h"
@@ -62,6 +63,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <limits>
#include <inttypes.h>
#include <rapidjson/rapidjson.h>
#include <rapidjson/document.h>
#include <rapidjson/error/en.h>
#ifdef ASSIMP_IMPORTER_GLTF_USE_OPEN3DGC
// Header files, Open3DGC.
# include <Open3DGC/o3dgcSC3DMCEncoder.h>
@@ -1064,6 +1069,5 @@ void glTFExporter::ExportAnimations()
} // End: for-loop mNumAnimations
}
#endif // ASSIMP_BUILD_NO_GLTF_EXPORTER
#endif // ASSIMP_BUILD_NO_EXPORT

View File

@@ -56,8 +56,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <assimp/scene.h>
#include <assimp/DefaultLogger.hpp>
#include <memory>
using namespace Assimp;
using namespace glTF;
@@ -78,6 +76,74 @@ static constexpr aiImporterDesc desc = {
"gltf glb"
};
namespace {
void SetMaterialColorProperty(const std::vector<int> &embeddedTexIdxs, Asset &, TexProperty prop, aiMaterial *mat,
aiTextureType texType, const char *pKey, unsigned int type, unsigned int idx) {
if (prop.texture) {
if (prop.texture->source) {
aiString uri(prop.texture->source->uri);
if (const int texIdx = embeddedTexIdxs[prop.texture->source.GetIndex()]; texIdx != -1) { // embedded
// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
uri.data[0] = '*';
uri.length = 1 + ASSIMP_itoa10(uri.data + 1, AI_MAXLEN - 1, texIdx);
}
mat->AddProperty(&uri, _AI_MATKEY_TEXTURE_BASE, texType, 0);
}
return;
}
aiColor4D col;
CopyValue(prop.color, col);
mat->AddProperty(&col, 1, pKey, type, idx);
}
void SetFace(aiFace &face, int a) {
face.mNumIndices = 1;
face.mIndices = new unsigned int[1];
face.mIndices[0] = a;
}
void SetFace(aiFace &face, int a, int b) {
face.mNumIndices = 2;
face.mIndices = new unsigned int[2];
face.mIndices[0] = a;
face.mIndices[1] = b;
}
void SetFace(aiFace &face, int a, int b, int c) {
face.mNumIndices = 3;
face.mIndices = new unsigned int[3];
face.mIndices[0] = a;
face.mIndices[1] = b;
face.mIndices[2] = c;
}
bool CheckValidFacesIndices(const aiFace *faces, unsigned nFaces, unsigned nVerts) {
for (unsigned i = 0; i < nFaces; ++i) {
for (unsigned j = 0; j < faces[i].mNumIndices; ++j) {
unsigned idx = faces[i].mIndices[j];
if (idx >= nVerts)
return false;
}
}
return true;
}
void createDefaultMaterial(aiScene *scene) {
if (scene == nullptr) {
return;
}
scene->mNumMaterials = 1;
scene->mMaterials = nullptr;
scene->mMaterials = new aiMaterial *[1];
scene->mMaterials[0] = new aiMaterial();
}
} // Anonymous namespace
glTFImporter::glTFImporter() :
mScene(nullptr) {
// empty
@@ -99,33 +165,15 @@ bool glTFImporter::CanRead(const std::string &pFile, IOSystem *pIOHandler, bool
return false;
}
}
inline void SetMaterialColorProperty(const std::vector<int> &embeddedTexIdxs, Asset &, TexProperty prop, aiMaterial *mat,
aiTextureType texType, const char *pKey, unsigned int type, unsigned int idx) {
if (prop.texture) {
if (prop.texture->source) {
aiString uri(prop.texture->source->uri);
if (const int texIdx = embeddedTexIdxs[prop.texture->source.GetIndex()]; texIdx != -1) { // embedded
// setup texture reference string (copied from ColladaLoader::FindFilenameForEffectTexture)
uri.data[0] = '*';
uri.length = 1 + ASSIMP_itoa10(uri.data + 1, AI_MAXLEN - 1, texIdx);
}
mat->AddProperty(&uri, _AI_MATKEY_TEXTURE_BASE, texType, 0);
}
void glTFImporter::ImportMaterials(Asset &r) const {
mScene->mNumMaterials = r.materials.Size();
if (mScene->mNumMaterials == 0) {
createDefaultMaterial(mScene);
return;
}
aiColor4D col;
CopyValue(prop.color, col);
mat->AddProperty(&col, 1, pKey, type, idx);
}
void glTFImporter::ImportMaterials(Asset &r) {
mScene->mNumMaterials = static_cast<unsigned int>(r.materials.Size());
mScene->mMaterials = new aiMaterial *[mScene->mNumMaterials];
for (unsigned int i = 0; i < mScene->mNumMaterials; ++i) {
aiMaterial *aimat = mScene->mMaterials[i] = new aiMaterial();
@@ -148,47 +196,6 @@ void glTFImporter::ImportMaterials(Asset &r) {
aimat->AddProperty(&mat.shininess, 1, AI_MATKEY_SHININESS);
}
}
if (mScene->mNumMaterials == 0) {
mScene->mNumMaterials = 1;
// Delete the array of length zero created above.
delete[] mScene->mMaterials;
mScene->mMaterials = nullptr;
mScene->mMaterials = new aiMaterial *[1];
mScene->mMaterials[0] = new aiMaterial();
}
}
static void SetFace(aiFace &face, int a) {
face.mNumIndices = 1;
face.mIndices = new unsigned int[1];
face.mIndices[0] = a;
}
static void SetFace(aiFace &face, int a, int b) {
face.mNumIndices = 2;
face.mIndices = new unsigned int[2];
face.mIndices[0] = a;
face.mIndices[1] = b;
}
static void SetFace(aiFace &face, int a, int b, int c) {
face.mNumIndices = 3;
face.mIndices = new unsigned int[3];
face.mIndices[0] = a;
face.mIndices[1] = b;
face.mIndices[2] = c;
}
static bool CheckValidFacesIndices(const aiFace *faces, unsigned nFaces, unsigned nVerts) {
for (unsigned i = 0; i < nFaces; ++i) {
for (unsigned j = 0; j < faces[i].mNumIndices; ++j) {
unsigned idx = faces[i].mIndices[j];
if (idx >= nVerts)
return false;
}
}
return true;
}
void glTFImporter::ImportMeshes(Asset &r) {
@@ -452,7 +459,7 @@ void glTFImporter::ImportMeshes(Asset &r) {
CopyVector(meshes, mScene->mMeshes, mScene->mNumMeshes);
}
void glTFImporter::ImportCameras(Asset &r) {
void glTFImporter::ImportCameras(Asset &r) const {
if (!r.cameras.Size()) {
return;
}
@@ -460,29 +467,30 @@ void glTFImporter::ImportCameras(Asset &r) {
mScene->mNumCameras = r.cameras.Size();
mScene->mCameras = new aiCamera *[r.cameras.Size()];
for (size_t i = 0; i < r.cameras.Size(); ++i) {
Camera &cam = r.cameras[i];
aiCamera *aicam = mScene->mCameras[i] = new aiCamera();
const Camera &cam = r.cameras[i];
mScene->mCameras[i] = new aiCamera();
const auto aiCameraPtr = mScene->mCameras[i];
if (cam.type == Camera::Perspective) {
aicam->mAspect = cam.perspective.aspectRatio;
aicam->mHorizontalFOV = cam.perspective.yfov * ((aicam->mAspect == 0.f) ? 1.f : aicam->mAspect);
aicam->mClipPlaneFar = cam.perspective.zfar;
aicam->mClipPlaneNear = cam.perspective.znear;
aiCameraPtr->mAspect = cam.perspective.aspectRatio;
aiCameraPtr->mHorizontalFOV = cam.perspective.yfov * ((aiCameraPtr->mAspect == 0.f) ? 1.f : aiCameraPtr->mAspect);
aiCameraPtr->mClipPlaneFar = cam.perspective.zfar;
aiCameraPtr->mClipPlaneNear = cam.perspective.znear;
} else {
aicam->mClipPlaneFar = cam.ortographic.zfar;
aicam->mClipPlaneNear = cam.ortographic.znear;
aicam->mHorizontalFOV = 0.0;
aicam->mAspect = 1.0f;
aiCameraPtr->mClipPlaneFar = cam.ortographic.zfar;
aiCameraPtr->mClipPlaneNear = cam.ortographic.znear;
aiCameraPtr->mHorizontalFOV = 0.0;
aiCameraPtr->mAspect = 1.0f;
if (0.f != cam.ortographic.ymag) {
aicam->mAspect = cam.ortographic.xmag / cam.ortographic.ymag;
aiCameraPtr->mAspect = cam.ortographic.xmag / cam.ortographic.ymag;
}
}
}
}
void glTFImporter::ImportLights(Asset &r) {
if (!r.lights.Size()) return;
void glTFImporter::ImportLights(Asset &r) const {
if (!r.lights.Size()) {
return;
}
mScene->mNumLights = r.lights.Size();
mScene->mLights = new aiLight *[r.lights.Size()];
@@ -529,7 +537,7 @@ aiNode *ImportNode(aiScene *pScene, Asset &r, std::vector<unsigned int> &meshOff
aiNode *ainode = new aiNode(node.id);
if (!node.children.empty()) {
ainode->mNumChildren = unsigned(node.children.size());
ainode->mNumChildren = static_cast<unsigned>(node.children.size());
ainode->mChildren = new aiNode *[ainode->mNumChildren];
for (unsigned int i = 0; i < ainode->mNumChildren; ++i) {
@@ -578,7 +586,7 @@ aiNode *ImportNode(aiScene *pScene, Asset &r, std::vector<unsigned int> &meshOff
int k = 0;
for (size_t i = 0; i < node.meshes.size(); ++i) {
int idx = node.meshes[i].GetIndex();
const int idx = node.meshes[i].GetIndex();
for (unsigned int j = meshOffsets[idx]; j < meshOffsets[idx + 1]; ++j, ++k) {
ainode->mMeshes[k] = j;
}
@@ -597,13 +605,14 @@ aiNode *ImportNode(aiScene *pScene, Asset &r, std::vector<unsigned int> &meshOff
}
void glTFImporter::ImportNodes(Asset &r) {
if (!r.scene) return;
if (!r.scene) {
return;
}
std::vector<Ref<Node>> rootNodes = r.scene->nodes;
// The root nodes
unsigned int numRootNodes = static_cast<unsigned>(rootNodes.size());
if (numRootNodes == 1) { // a single root node: use it
if (auto numRootNodes = static_cast<unsigned>(rootNodes.size()); numRootNodes == 1) { // a single root node: use it
mScene->mRootNode = ImportNode(mScene, r, meshOffsets, rootNodes[0]);
} else if (numRootNodes > 1) { // more than one root node: create a fake root
aiNode *root = new aiNode("ROOT");
@@ -648,11 +657,10 @@ void glTFImporter::ImportEmbeddedTextures(Asset &r) {
tex->mFilename = img.name;
tex->mWidth = static_cast<unsigned int>(length);
tex->mHeight = 0;
tex->pcData = reinterpret_cast<aiTexel *>(data);
tex->pcData = static_cast<aiTexel *>(data);
if (!img.mimeType.empty()) {
const char *ext = strchr(img.mimeType.c_str(), '/') + 1;
if (ext) {
if (const char *ext = strchr(img.mimeType.c_str(), '/') + 1) {
if (strncmp(ext, "jpeg", 4) == 0) {
ext = "jpg";
}
@@ -666,7 +674,7 @@ void glTFImporter::ImportEmbeddedTextures(Asset &r) {
}
}
void glTFImporter::ImportCommonMetadata(Asset &a) {
void glTFImporter::ImportCommonMetadata(const Asset &a) const {
ai_assert(mScene->mMetaData == nullptr);
const bool hasVersion = !a.asset.version.empty();

View File

@@ -70,12 +70,12 @@ protected:
private:
void ImportEmbeddedTextures(glTF::Asset &a);
void ImportMaterials(glTF::Asset &a);
void ImportMaterials(glTF::Asset &a) const;
void ImportMeshes(glTF::Asset &a);
void ImportCameras(glTF::Asset &a);
void ImportLights(glTF::Asset &a);
void ImportCameras(glTF::Asset &a) const;
void ImportLights(glTF::Asset &a) const;
void ImportNodes(glTF::Asset &a);
void ImportCommonMetadata(glTF::Asset &a);
void ImportCommonMetadata(const glTF::Asset &a) const;
private:
std::vector<unsigned int> meshOffsets;

View File

@@ -58,7 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GLTF2ASSET_H_INC
#define GLTF2ASSET_H_INC
#if !defined(ASSIMP_BUILD_NO_GLTF_IMPORTER) && !defined(ASSIMP_BUILD_NO_GLTF2_IMPORTER)
//#if !defined(ASSIMP_BUILD_NO_GLTF_IMPORTER) && !defined(ASSIMP_BUILD_NO_GLTF2_IMPORTER)
#include <assimp/Exceptional.h>
@@ -1283,6 +1283,6 @@ inline std::string getContextForErrorMessages(const std::string &id, const std::
// Include the implementation of the methods
#include "glTF2Asset.inl"
#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
//#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
#endif // GLTF2ASSET_H_INC

View File

@@ -57,8 +57,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef GLTF2ASSETWRITER_H_INC
#define GLTF2ASSETWRITER_H_INC
#if !defined(ASSIMP_BUILD_NO_GLTF_IMPORTER) && !defined(ASSIMP_BUILD_NO_GLTF2_IMPORTER)
#include "glTF2Asset.h"
namespace glTF2
@@ -98,6 +96,4 @@ public:
// Include the implementation of the methods
#include "glTF2AssetWriter.inl"
#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
#endif // GLTF2ASSETWRITER_H_INC

View File

@@ -64,6 +64,10 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
#include <iostream>
#include <rapidjson/rapidjson.h>
#include <rapidjson/document.h>
#include <rapidjson/error/en.h>
using namespace rapidjson;
using namespace Assimp;

View File

@@ -45,8 +45,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_GLTF2EXPORTER_H_INC
#define AI_GLTF2EXPORTER_H_INC
#if !defined(ASSIMP_BUILD_NO_GLTF_IMPORTER) && !defined(ASSIMP_BUILD_NO_GLTF2_IMPORTER)
#include <assimp/material.h>
#include <assimp/types.h>
#include <assimp/defs.h>
@@ -150,6 +148,4 @@ private:
} // namespace Assimp
#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
#endif // AI_GLTF2EXPORTER_H_INC

View File

@@ -65,6 +65,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <rapidjson/document.h>
#include <rapidjson/rapidjson.h>
#include <rapidjson/error/en.h>
using namespace Assimp;
using namespace glTF2;

View File

@@ -38,15 +38,11 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
----------------------------------------------------------------------
*/
#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
#include "AssetLib/glTFCommon/glTFCommon.h"
namespace glTFCommon {
using namespace glTFCommon::Util;
namespace Util {
namespace glTFCommon::Util {
bool ParseDataURI(const char *const_uri, size_t uriLen, DataURI &out) {
if (nullptr == const_uri) {
@@ -111,7 +107,4 @@ bool ParseDataURI(const char *const_uri, size_t uriLen, DataURI &out) {
return true;
}
} // namespace Util
} // namespace glTFCommon
#endif
} // namespace glTFCommon::Uti

View File

@@ -41,8 +41,6 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#ifndef AI_GLFTCOMMON_H_INC
#define AI_GLFTCOMMON_H_INC
#ifndef ASSIMP_BUILD_NO_GLTF_IMPORTER
#include <assimp/Exceptional.h>
#include <assimp/DefaultLogger.hpp>
@@ -532,6 +530,4 @@ inline Value *FindNumber(Value &val, const char *id) {
} // namespace glTFCommon
#endif // ASSIMP_BUILD_NO_GLTF_IMPORTER
#endif // AI_GLFTCOMMON_H_INC

View File

@@ -602,6 +602,12 @@ ADD_ASSIMP_IMPORTER( XGL
AssetLib/XGL/XGLLoader.h
)
SET( FBX_COMMON_SRCS
AssetLib/FBX/FBXUtil.h
AssetLib/FBX/FBXUtil.cpp
AssetLib/FBX/FBXCommon.h
)
ADD_ASSIMP_IMPORTER( FBX
AssetLib/FBX/FBXImporter.cpp
AssetLib/FBX/FBXCompileConfig.h
@@ -613,8 +619,6 @@ ADD_ASSIMP_IMPORTER( FBX
AssetLib/FBX/FBXImportSettings.h
AssetLib/FBX/FBXConverter.h
AssetLib/FBX/FBXConverter.cpp
AssetLib/FBX/FBXUtil.h
AssetLib/FBX/FBXUtil.cpp
AssetLib/FBX/FBXDocument.h
AssetLib/FBX/FBXDocument.cpp
AssetLib/FBX/FBXProperties.h
@@ -628,7 +632,6 @@ ADD_ASSIMP_IMPORTER( FBX
AssetLib/FBX/FBXDeformer.cpp
AssetLib/FBX/FBXBinaryTokenizer.cpp
AssetLib/FBX/FBXDocumentUtil.cpp
AssetLib/FBX/FBXCommon.h
)
if (NOT ASSIMP_NO_EXPORT)
@@ -1348,6 +1351,8 @@ SET( assimp_src
${ASSIMP_LOADER_SRCS}
${ASSIMP_EXPORTER_SRCS}
${FBX_COMMON_SRCS}
# Third-party libraries
${unzip_compile_SRCS}
${Poly2Tri_SRCS}

View File

@@ -51,7 +51,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <vector>
#include <utility>
#// Forward declarations
// Forward declarations
class DeboneTest;
namespace Assimp {
@@ -72,7 +72,9 @@ public:
~DeboneProcess() override = default;
// -------------------------------------------------------------------
/** Returns whether the processing step is present in the given flag.
/**
* @brief Returns whether the processing step is present in the given flag.
*
* @param pFlags The processing flags the importer was called with.
* A bitwise combination of #aiPostProcessSteps.
* @return true if the process is present in this flag fields,
@@ -81,7 +83,9 @@ public:
bool IsActive( unsigned int pFlags) const override;
// -------------------------------------------------------------------
/** Called prior to ExecuteOnScene().
/**
* @brief Called prior to ExecuteOnScene().
*
* The function is a request to the process to update its configuration
* basing on the Importer's configuration property list.
*/
@@ -89,33 +93,41 @@ public:
protected:
// -------------------------------------------------------------------
/** Executes the post processing step on the given imported data.
* At the moment a process is not supposed to fail.
* @param pScene The imported data to work at.
*/
/**
* @brief Executes the post processing step on the given imported data.
*
* At the moment a process is not supposed to fail.
* @param pScene The imported data to work at.
*/
void Execute( aiScene* pScene) override;
// -------------------------------------------------------------------
/** Counts bones total/removable in a given mesh.
/**
* @brief Counts bones total/removable in a given mesh.
*
* @param pMesh The mesh to process.
* @return false in case of an error.
*/
bool ConsiderMesh( const aiMesh* pMesh);
/// Splits the given mesh by bone count.
/// @brief Splits the given mesh by bone count.
/// @param pMesh the Mesh to split. Is not changed at all, but might be superfluous in case it was split.
/// @param poNewMeshes Array of submeshes created in the process. Empty if splitting was not necessary.
void SplitMesh(const aiMesh* pMesh, std::vector< std::pair< aiMesh*,const aiBone* > >& poNewMeshes) const;
/// Recursively updates the node's mesh list to account for the changed mesh list
/// @brief Recursively updates the node's mesh list to account for the changed mesh list
/// @param pNode The root node to update.
void UpdateNode(aiNode* pNode) const;
// -------------------------------------------------------------------
// Apply transformation to a mesh
/// @brief Apply transformation to a mesh
/// @param mesh The mesh to apply the transformation
/// @param mat The transformation to appy
void ApplyTransform(aiMesh* mesh, const aiMatrix4x4& mat)const;
public:
/** Number of bones present in the scene. */
unsigned int mNumBones;
/// Number of bones present in the scene.
unsigned int mNumBones;
unsigned int mNumBonesCanDoWithout;
float mThreshold;

View File

@@ -2,7 +2,7 @@
Open Asset Import Library (assimp)
----------------------------------------------------------------------
Copyright (c) 2006-2020, assimp team
Copyright (c) 2006-2025, assimp team
All rights reserved.
@@ -58,6 +58,7 @@ using AiAssertHandler = void (*)(const char* failedExpression, const char* file,
// ---------------------------------------------------------------------------
/**
* @brief Set the assert handler.
* @param handler The assertion handler to use.
*/
ASSIMP_API void setAiAssertHandler(AiAssertHandler handler);
@@ -65,12 +66,18 @@ ASSIMP_API void setAiAssertHandler(AiAssertHandler handler);
/** The assert handler which is set by default.
*
* @brief This issues a message to stderr and calls abort.
* @param failedExpression The failed expression as a string.
* @param file The name of the source file.
* @param line The line in the source file.
*/
AI_WONT_RETURN ASSIMP_API void defaultAiAssertHandler(const char* failedExpression, const char* file, int line) AI_WONT_RETURN_SUFFIX;
// ---------------------------------------------------------------------------
/**
* @brief Dispatches an assert violation to the assert handler.
* @brief Dispatches an assert violation to the assert handler.
* @param failedExpression The failed expression as a string.
* @param file The name of the source file.
* @param line The line in the source file.
*/
ASSIMP_API void aiAssertViolation(const char* failedExpression, const char* file, int line);

View File

@@ -70,7 +70,8 @@ class BaseProcess;
class SharedPostProcessInfo;
class IOStream;
// utility to do char4 to uint32 in a portable manner
/// @def AI_MAKE_MAGIC
/// @brief Utility to do char4 to uint32 in a portable manner
#define AI_MAKE_MAGIC(string) ((uint32_t)((string[0] << 24) + \
(string[1] << 16) + (string[2] << 8) + string[3]))
@@ -188,60 +189,7 @@ public:
* @param extension set to collect file extensions in*/
void GetExtensionList(std::set<std::string> &extensions);
protected:
double importerScale = 1.0;
double fileScale = 1.0;
// -------------------------------------------------------------------
/** Imports the given file into the given scene structure. The
* function is expected to throw an ImportErrorException if there is
* an error. If it terminates normally, the data in aiScene is
* expected to be correct. Override this function to implement the
* actual importing.
* <br>
* The output scene must meet the following requirements:<br>
* <ul>
* <li>At least a root node must be there, even if its only purpose
* is to reference one mesh.</li>
* <li>aiMesh::mPrimitiveTypes may be 0. The types of primitives
* in the mesh are determined automatically in this case.</li>
* <li>the vertex data is stored in a pseudo-indexed "verbose" format.
* In fact this means that every vertex that is referenced by
* a face is unique. Or the other way round: a vertex index may
* not occur twice in a single aiMesh.</li>
* <li>aiAnimation::mDuration may be -1. Assimp determines the length
* of the animation automatically in this case as the length of
* the longest animation channel.</li>
* <li>aiMesh::mBitangents may be nullptr if tangents and normals are
* given. In this case bitangents are computed as the cross product
* between normal and tangent.</li>
* <li>There needn't be a material. If none is there a default material
* is generated. However, it is recommended practice for loaders
* to generate a default material for yourself that matches the
* default material setting for the file format better than Assimp's
* generic default material. Note that default materials *should*
* be named AI_DEFAULT_MATERIAL_NAME if they're just color-shaded
* or AI_DEFAULT_TEXTURED_MATERIAL_NAME if they define a (dummy)
* texture. </li>
* </ul>
* If the AI_SCENE_FLAGS_INCOMPLETE-Flag is <b>not</b> set:<ul>
* <li> at least one mesh must be there</li>
* <li> there may be no meshes with 0 vertices or faces</li>
* </ul>
* This won't be checked (except by the validation step): Assimp will
* crash if one of the conditions is not met!
*
* @param pFile Path of the file to be imported.
* @param pScene The scene object to hold the imported data.
* nullptr is not a valid parameter.
* @param pIOHandler The IO handler to use for any file access.
* nullptr is not a valid parameter. */
virtual void InternReadFile(
const std::string &pFile,
aiScene *pScene,
IOSystem *pIOHandler) = 0;
public: // static utilities
// static utilities
// -------------------------------------------------------------------
/** A utility for CanRead().
*
@@ -394,6 +342,59 @@ public: // static utilities
}
}
protected:
double importerScale = 1.0;
double fileScale = 1.0;
// -------------------------------------------------------------------
/** Imports the given file into the given scene structure. The
* function is expected to throw an ImportErrorException if there is
* an error. If it terminates normally, the data in aiScene is
* expected to be correct. Override this function to implement the
* actual importing.
* <br>
* The output scene must meet the following requirements:<br>
* <ul>
* <li>At least a root node must be there, even if its only purpose
* is to reference one mesh.</li>
* <li>aiMesh::mPrimitiveTypes may be 0. The types of primitives
* in the mesh are determined automatically in this case.</li>
* <li>the vertex data is stored in a pseudo-indexed "verbose" format.
* In fact this means that every vertex that is referenced by
* a face is unique. Or the other way round: a vertex index may
* not occur twice in a single aiMesh.</li>
* <li>aiAnimation::mDuration may be -1. Assimp determines the length
* of the animation automatically in this case as the length of
* the longest animation channel.</li>
* <li>aiMesh::mBitangents may be nullptr if tangents and normals are
* given. In this case bitangents are computed as the cross product
* between normal and tangent.</li>
* <li>There needn't be a material. If none is there a default material
* is generated. However, it is recommended practice for loaders
* to generate a default material for yourself that matches the
* default material setting for the file format better than Assimp's
* generic default material. Note that default materials *should*
* be named AI_DEFAULT_MATERIAL_NAME if they're just color-shaded
* or AI_DEFAULT_TEXTURED_MATERIAL_NAME if they define a (dummy)
* texture. </li>
* </ul>
* If the AI_SCENE_FLAGS_INCOMPLETE-Flag is <b>not</b> set:<ul>
* <li> at least one mesh must be there</li>
* <li> there may be no meshes with 0 vertices or faces</li>
* </ul>
* This won't be checked (except by the validation step): Assimp will
* crash if one of the conditions is not met!
*
* @param pFile Path of the file to be imported.
* @param pScene The scene object to hold the imported data.
* nullptr is not a valid parameter.
* @param pIOHandler The IO handler to use for any file access.
* nullptr is not a valid parameter. */
virtual void InternReadFile(
const std::string &pFile,
aiScene *pScene,
IOSystem *pIOHandler) = 0;
private:
/* Pushes state into importer for the importer scale */
void UpdateImporterScale(Importer *pImp);

View File

@@ -147,7 +147,7 @@ private:
explicit DefaultLogger(LogSeverity severity);
// ----------------------------------------------------------------------
/** @briefDestructor */
/** @brief Destructor */
~DefaultLogger() override;
/** @brief Logs debug infos, only been written when severity level DEBUG or higher is set */

View File

@@ -52,15 +52,15 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <cmath>
// ------------------------------------------------------------------------------------------------
// Hashing function taken from
// http://www.azillionmonkeys.com/qed/hash.html
// (incremental version)
//
// This code is Copyright 2004-2008 by Paul Hsieh. It is used here in the belief that
// Assimp's license is considered compatible with Pauls's derivative license as specified
// on his web page.
//
// (stdint.h should have been been included here)
/// @brief Hashing function taken from
/// http://www.azillionmonkeys.com/qed/hash.html
/// (incremental version)
///
/// This code is Copyright 2004-2008 by Paul Hsieh. It is used here in the belief that
/// Assimp's license is considered compatible with Pauls's derivative license as specified
/// on his web page.
///
/// (stdint.h should have been been included here)
// ------------------------------------------------------------------------------------------------
#undef get16bits
#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__) \

View File

@@ -78,21 +78,23 @@ for(LineSplitter splitter(stream);splitter;++splitter) {
// ------------------------------------------------------------------------------------------------
class LineSplitter {
public:
/// The current line index in the data block.
typedef size_t line_idx;
// -----------------------------------------
/** construct from existing stream reader
note: trim is *always* assumed true if skyp_empty_lines==true
*/
/// @brief The class constructor.
/// @note trim is *always* assumed true if skyp_empty_lines==true
LineSplitter(StreamReaderLE& stream, bool skip_empty_lines = true, bool trim = true);
/// @brief The class destructor.
~LineSplitter() = default;
// -----------------------------------------
/** pseudo-iterator increment */
/// @brief pseudo-iterator increment
LineSplitter& operator++();
// -----------------------------------------
/// @brief pseudo-iterator increment
LineSplitter& operator++(int);
// -----------------------------------------
@@ -109,7 +111,9 @@ public:
const std::string* operator -> () const;
std::string operator* () const;
/// @brief Will return the end marker, end of the buffer plus one.
/// @return The end pointer marker.
const char *getEnd() const;
// -----------------------------------------
@@ -120,6 +124,8 @@ public:
/** line indices are zero-based, empty lines are included */
operator line_idx() const;
/// @brief Will return the current index.
/// @return The current index.
line_idx get_index() const;
// -----------------------------------------
@@ -139,19 +145,17 @@ public:
LineSplitter &operator = ( const LineSplitter & ) = delete;
private:
line_idx mIdx;
std::string mCur;
const char *mEnd;
StreamReaderLE& mStream;
bool mSwallow, mSkip_empty_lines, mTrim;
line_idx mIdx{0};
std::string mCur{};
const char *mEnd{nullptr};
StreamReaderLE &mStream;
bool mSwallow{false};
bool mSkip_empty_lines{ false };
bool mTrim{ false };
};
AI_FORCE_INLINE LineSplitter::LineSplitter(StreamReaderLE& stream, bool skip_empty_lines, bool trim ) :
mIdx(0),
mCur(),
mEnd(nullptr),
mStream(stream),
mSwallow(),
mSkip_empty_lines(skip_empty_lines),
mTrim(trim) {
mCur.reserve(1024);

View File

@@ -69,11 +69,11 @@ class ASSIMP_API LogStream
{
protected:
/** @brief Default constructor */
LogStream() AI_NO_EXCEPT;
LogStream() AI_NO_EXCEPT = default;
public:
/** @brief Virtual destructor */
virtual ~LogStream();
virtual ~LogStream() = default;
// -------------------------------------------------------------------
/** @brief Overwrite this for your own output methods
@@ -99,10 +99,6 @@ public:
}; // !class LogStream
inline LogStream::LogStream() AI_NO_EXCEPT = default;
inline LogStream::~LogStream() = default;
} // Namespace Assimp
#endif // INCLUDED_AI_LOGSTREAM_H

View File

@@ -94,7 +94,7 @@ public:
};
/** @brief Virtual destructor */
virtual ~Logger();
virtual ~Logger() = default;
// ----------------------------------------------------------------------
/** @brief Writes a debug message
@@ -184,12 +184,12 @@ public:
protected:
/**
* Default constructor
* @brief Default constructor
*/
Logger() AI_NO_EXCEPT;
Logger() AI_NO_EXCEPT = default;
/**
* Construction with a given log severity
* @brief Construction with a given log severity
*/
explicit Logger(LogSeverity severity);
@@ -253,18 +253,9 @@ protected:
}
protected:
LogSeverity m_Severity;
LogSeverity m_Severity{NORMAL};
};
// ----------------------------------------------------------------------------------
inline Logger::Logger() AI_NO_EXCEPT :
m_Severity(NORMAL) {
// empty
}
// ----------------------------------------------------------------------------------
inline Logger::~Logger() = default;
// ----------------------------------------------------------------------------------
inline Logger::Logger(LogSeverity severity) :
m_Severity(severity) {

View File

@@ -55,16 +55,16 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
// ---------------------------------------------------------------------------
// the original illum property
/// @brief The original illum property
#define AI_MATKEY_OBJ_ILLUM "$mat.illum", 0, 0
// ---------------------------------------------------------------------------
// ---------------------------------------------------------------------------
// Pure key names for all obj texture-related properties
/// @brief Pure key names for all obj texture-related properties
//! @cond MATS_DOC_FULL
// support for bump -bm
/// @brief Support for bump -bm
#define _AI_MATKEY_OBJ_BUMPMULT_BASE "$tex.bumpmult"
//! @endcond
@@ -80,5 +80,4 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
//! @endcond
#endif
#endif // AI_OBJMATERIAL_H_INC

View File

@@ -59,48 +59,69 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
// NOTE: the functions below are mostly intended as replacement for
// std::upper, std::lower, std::isupper, std::islower, std::isspace.
// we don't bother of locales. We don't want them. We want reliable
// (i.e. identical) results across all locales.
/// NOTE: the functions below are mostly intended as replacement for
/// std::upper, std::lower, std::isupper, std::islower, std::isspace.
/// we don't bother of locales. We don't want them. We want reliable
/// (i.e. identical) results across all locales, because we had a lot
/// of issues in the past .
// The functions below accept any character type, but know only
// about ASCII. However, UTF-32 is the only safe ASCII superset to
// use since it doesn't have multi-byte sequences.
/// The functions below accept any character type, but know only
/// about ASCII. However, UTF-32 is the only safe ASCII superset to
/// use since it doesn't have multi-byte sequences.
static const unsigned int BufferSize = 4096;
static constexpr unsigned int BufferSize = 4096;
// ---------------------------------------------------------------------------------
/// @brief Returns true, if the character is upper-case.
/// @param in The character to test.
/// @return true if upper-case, false if not.
template <class char_t>
AI_FORCE_INLINE bool IsUpper(char_t in) {
return (in >= (char_t)'A' && in <= (char_t)'Z');
}
// ---------------------------------------------------------------------------------
/// @brief Returns true, if the character is lower-case.
/// @param in The character to test.
/// @return true if lower-case, false if not.
template <class char_t>
AI_FORCE_INLINE bool IsLower(char_t in) {
return (in >= (char_t)'a' && in <= (char_t)'z');
}
// ---------------------------------------------------------------------------------
/// @brief Returns true, if the character is a space.
/// @param in The character to test.
/// @return true if a space, false if not.
template <class char_t>
AI_FORCE_INLINE bool IsSpace(char_t in) {
return (in == (char_t)' ' || in == (char_t)'\t');
}
// ---------------------------------------------------------------------------------
/// @brief Returns true, if the character is a line end.
/// @param in The character to test.
/// @return true if a line end, false if not.
template <class char_t>
AI_FORCE_INLINE bool IsLineEnd(char_t in) {
return (in == (char_t)'\r' || in == (char_t)'\n' || in == (char_t)'\0' || in == (char_t)'\f');
}
// ---------------------------------------------------------------------------------
/// @brief Returns true, if the character is a space or a line end.
/// @param in The character to test.
/// @return true if a space or a line end, false if not.
template <class char_t>
AI_FORCE_INLINE bool IsSpaceOrNewLine(char_t in) {
return IsSpace<char_t>(in) || IsLineEnd<char_t>(in);
}
// ---------------------------------------------------------------------------------
/// @brief Will skip all spaces in a buffer.
/// @param in The incoming buffer.
/// @param out The buffer with skipped data.
/// @param end The end of the buffer.
/// @return true if valid.
template <class char_t>
AI_FORCE_INLINE bool SkipSpaces(const char_t *in, const char_t **out, const char_t *end) {
while ((*in == (char_t)' ' || *in == (char_t)'\t') && in != end) {
@@ -111,12 +132,21 @@ AI_FORCE_INLINE bool SkipSpaces(const char_t *in, const char_t **out, const char
}
// ---------------------------------------------------------------------------------
/// @brief Will skip all spaces in a buffer in-situ.
/// @param inout The in/out buffer.
/// @param end The end of the buffer.
/// @return true if valid.
template <class char_t>
AI_FORCE_INLINE bool SkipSpaces(const char_t **inout, const char_t *end) {
return SkipSpaces<char_t>(*inout, inout, end);
}
// ---------------------------------------------------------------------------------
/// @brief Will skip a line.
/// @param in The incoming buffer.
/// @param out The buffer with skipped data.
/// @param end The end of the buffer.
/// @return true if valid.
template <class char_t>
AI_FORCE_INLINE bool SkipLine(const char_t *in, const char_t **out, const char_t *end) {
while ((*in != (char_t)'\r' && *in != (char_t)'\n' && *in != (char_t)'\0') && *in != (char_t)'#' && in != end) {
@@ -132,12 +162,20 @@ AI_FORCE_INLINE bool SkipLine(const char_t *in, const char_t **out, const char_t
}
// ---------------------------------------------------------------------------------
/// @brief Will skip a line in-situ.
/// @param in The in/out buffer.
/// @param end The end of the buffer.
/// @return true if valid.
template <class char_t>
AI_FORCE_INLINE bool SkipLine(const char_t **inout, const char_t *end) {
return SkipLine<char_t>(*inout, inout, end);
}
// ---------------------------------------------------------------------------------
/// @brief Returns true, if the character is a space or a line end.
/// @param in The character to test.
/// @param out The buffer with the skipped data.
/// @return true if valid.
template <class char_t>
AI_FORCE_INLINE bool SkipSpacesAndLineEnd(const char_t *in, const char_t **out, const char_t *end) {
while ((*in == (char_t)' ' || *in == (char_t)'\t' || *in == (char_t)'\r' || *in == (char_t)'\n') && in != end) {
@@ -148,12 +186,20 @@ AI_FORCE_INLINE bool SkipSpacesAndLineEnd(const char_t *in, const char_t **out,
}
// ---------------------------------------------------------------------------------
/// @brief Returns true, if the character is a space or a line end.
/// @param in The character to test.
/// @param out The buffer with the skipped data.
/// @return true if valid.
template <class char_t>
AI_FORCE_INLINE bool SkipSpacesAndLineEnd(const char_t **inout, const char_t *end) {
return SkipSpacesAndLineEnd<char_t>(*inout, inout, end);
}
// ---------------------------------------------------------------------------------
/// @brief Will return point showing to the next line.
/// @param buffer The in buffer.
/// @param out The next line.
/// @return true if a new lne was found, else false.
template <class char_t>
AI_FORCE_INLINE bool GetNextLine(const char_t *&buffer, char_t out[BufferSize]) {
if ((char_t)'\0' == *buffer) {
@@ -175,12 +221,20 @@ AI_FORCE_INLINE bool GetNextLine(const char_t *&buffer, char_t out[BufferSize])
}
// ---------------------------------------------------------------------------------
/// @brief Returns true, if the character is a number.
/// @param in The character to test.
/// @return true if a number, false if not.
template <class char_t>
AI_FORCE_INLINE bool IsNumeric(char_t in) {
return (in >= '0' && in <= '9') || '-' == in || '+' == in;
}
// ---------------------------------------------------------------------------------
/// @brief Will check an incoming buffer for a given token.
/// @param in The incoming buffer.
/// @param token The token to check for.
/// @param len the buffer length.
/// @return true if token was found, false if not.
template <class char_t>
AI_FORCE_INLINE bool TokenMatch(char_t *&in, const char *token, unsigned int len) {
if (!::strncmp(token, in, len) && IsSpaceOrNewLine(in[len])) {
@@ -196,11 +250,11 @@ AI_FORCE_INLINE bool TokenMatch(char_t *&in, const char *token, unsigned int len
return false;
}
// ---------------------------------------------------------------------------------
/** @brief Case-ignoring version of TokenMatch
* @param in Input
* @param token Token to check for
* @param len Number of characters to check
*/
/// @brief Case-ignoring version of TokenMatch
/// @param in Input
/// @param token Token to check for
/// @param len Number of characters to check
/// @return true if token was found, false if not.
AI_FORCE_INLINE bool TokenMatchI(const char *&in, const char *token, unsigned int len) {
if (!ASSIMP_strincmp(token, in, len) && IsSpaceOrNewLine(in[len])) {
in += len + 1;
@@ -210,6 +264,9 @@ AI_FORCE_INLINE bool TokenMatchI(const char *&in, const char *token, unsigned in
}
// ---------------------------------------------------------------------------------
/// @brief Will skip the next token.
/// @param in The incoming buffer.
/// @param end The end marker of the buffer.
AI_FORCE_INLINE void SkipToken(const char *&in, const char *end) {
SkipSpaces(&in, end);
while (!IsSpaceOrNewLine(*in)) {
@@ -218,6 +275,10 @@ AI_FORCE_INLINE void SkipToken(const char *&in, const char *end) {
}
// ---------------------------------------------------------------------------------
/// @brief Will return the next token as a string.
/// @param in The incoming buffer.
/// @param end The end marker of the buffer.
/// @return The next token.
AI_FORCE_INLINE std::string GetNextToken(const char *&in, const char *end) {
SkipSpacesAndLineEnd(&in, end);
const char *cur = in;
@@ -228,12 +289,11 @@ AI_FORCE_INLINE std::string GetNextToken(const char *&in, const char *end) {
}
// ---------------------------------------------------------------------------------
/** @brief Will perform a simple tokenize.
* @param str String to tokenize.
* @param tokens Array with tokens, will be empty if no token was found.
* @param delimiters Delimiter for tokenize.
* @return Number of found token.
*/
/// @brief Will perform a simple tokenize.
/// @param str String to tokenize.
/// @param tokens Array with tokens, will be empty if no token was found.
/// @param delimiters Delimiter for tokenize.
/// @return Number of found token.
template <class string_type>
AI_FORCE_INLINE unsigned int tokenize(const string_type &str, std::vector<string_type> &tokens,
const string_type &delimiters) {
@@ -258,6 +318,10 @@ AI_FORCE_INLINE unsigned int tokenize(const string_type &str, std::vector<string
return static_cast<unsigned int>(tokens.size());
}
// ---------------------------------------------------------------------------------
/// @brief Will convert the given string to lowercase with stl-strings.
/// @param str The stl-string to convert.
/// @return The lowercase string as a stl-string.
inline std::string ai_stdStrToLower(const std::string &str) {
std::string out(str);
for (size_t i = 0; i < str.size(); ++i) {

View File

@@ -56,45 +56,46 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <map>
namespace Assimp {
namespace Profiling {
namespace Assimp::Profiling {
using namespace Formatter;
// ------------------------------------------------------------------------------------------------
/** Simple wrapper around boost::timer to simplify reporting. Timings are automatically
* dumped to the log file.
*/
/// @brief Simple wrapper around boost::timer to simplify reporting.
///
/// Timings are automatically dumped to the log file.
class Profiler {
public:
/// @brief The class constructor.
Profiler() = default;
/// @brief The class destructor.
~Profiler() = default;
/** Start a named timer */
/// @brief Starts a named timer.
/// @param region The profiling region name.
void BeginRegion(const std::string& region) {
regions[region] = std::chrono::system_clock::now();
mRegions[region] = std::chrono::system_clock::now();
ASSIMP_LOG_DEBUG("START `",region,"`");
}
/** End a specific named timer and write its end time to the log */
/// @brief End a specific named timer and write its end time to the log.
/// @param region The profiling region name.
void EndRegion(const std::string& region) {
RegionMap::const_iterator it = regions.find(region);
if (it == regions.end()) {
if (auto it = mRegions.find(region); it == mRegions.end()) {
return;
}
std::chrono::duration<double> elapsedSeconds = std::chrono::system_clock::now() - regions[region];
auto elapsedSeconds = std::chrono::system_clock::now() - mRegions[region];
ASSIMP_LOG_DEBUG("END `",region,"`, dt= ", elapsedSeconds.count()," s");
}
private:
typedef std::map<std::string,std::chrono::time_point<std::chrono::system_clock>> RegionMap;
RegionMap regions;
using RegionMap = std::map<std::string,std::chrono::time_point<std::chrono::system_clock>>;
RegionMap mRegions{};
};
}
}
} // namespace Assimp::Profiling
#endif // AI_INCLUDED_PROFILER_H

View File

@@ -62,32 +62,33 @@ namespace Assimp {
* module.
*/
class ASSIMP_API CommentRemover {
// class cannot be instanced
CommentRemover() {}
public:
// class cannot be instanced
CommentRemover() = delete;
~CommentRemover() = delete;
//! Remove single-line comments. The end of a line is
//! expected to be either NL or CR or NLCR.
//! \param szComment The start sequence of the comment, e.g. "//"
//! \param szBuffer Buffer to work with
//! \param chReplacement Character to be used as replacement
//! for commented lines. By default this is ' '
/// @brief Remove single-line comments.
/// The end of a line is expected to be either NL or CR or NLCR.
/// @param szComment The start sequence of the comment, e.g. "//"
/// @param szBuffer Buffer to work with
/// @param chReplacement Character to be used as replacement
/// for commented lines. By default this is ' '
static void RemoveLineComments(const char* szComment,
char* szBuffer, char chReplacement = ' ');
//! Remove multi-line comments. The end of a line is
//! expected to be either NL or CR or NLCR. Multi-line comments
//! may not be nested (as in C).
//! \param szCommentStart The start sequence of the comment, e.g. "/*"
//! \param szCommentEnd The end sequence of the comment, e.g. "*/"
//! \param szBuffer Buffer to work with
//! \param chReplacement Character to be used as replacement
//! for commented lines. By default this is ' '
/// @brief Remove multi-line comments.
/// The end of a line is expected to be either NL or CR or NLCR. Multi-line comments
/// may not be nested (as in C).
/// @param szCommentStart The start sequence of the comment, e.g. "/*"
/// @param szCommentEnd The end sequence of the comment, e.g. "*/"
/// @param szBuffer Buffer to work with
/// @param chReplacement Character to be used as replacement
/// for commented lines. By default this is ' '
static void RemoveMultiLineComments(const char* szCommentStart,
const char* szCommentEnd,char* szBuffer,
char chReplacement = ' ');
};
} // ! Assimp
#endif // !! AI_REMOVE_COMMENTS_H_INC

View File

@@ -81,32 +81,30 @@ namespace Assimp {
* Describes to which node a scene must be attached to.
*/
struct AttachmentInfo {
AttachmentInfo() :
scene(nullptr),
attachToNode(nullptr) {}
AttachmentInfo() = default;
AttachmentInfo(aiScene *_scene, aiNode *_attachToNode) : scene(_scene), attachToNode(_attachToNode) {
// empty
}
~AttachmentInfo() = default;
AttachmentInfo(aiScene *_scene, aiNode *_attachToNode) :
scene(_scene), attachToNode(_attachToNode) {}
aiScene *scene;
aiNode *attachToNode;
aiScene *scene{nullptr};
aiNode *attachToNode{nullptr};
};
// ---------------------------------------------------------------------------
/// @brief Helper data structure for SceneCombiner.
struct NodeAttachmentInfo {
NodeAttachmentInfo() :
node(nullptr),
attachToNode(nullptr),
resolved(false),
src_idx(SIZE_MAX) {}
NodeAttachmentInfo() = default;
~NodeAttachmentInfo() = default;
NodeAttachmentInfo(aiNode *_scene, aiNode *_attachToNode, size_t idx) :
node(_scene), attachToNode(_attachToNode), resolved(false), src_idx(idx) {}
node(_scene), attachToNode(_attachToNode), src_idx(idx) {
// empty
}
aiNode *node;
aiNode *attachToNode;
bool resolved;
size_t src_idx;
aiNode *node{nullptr};
aiNode *attachToNode{nullptr};
bool resolved{false};
size_t src_idx{SIZE_MAX};
};
// ---------------------------------------------------------------------------
@@ -139,7 +137,7 @@ struct NodeAttachmentInfo {
*/
#define AI_INT_MERGE_SCENE_GEN_UNIQUE_NAMES_IF_NECESSARY 0x10
typedef std::pair<aiBone *, unsigned int> BoneSrcIndex;
using BoneSrcIndex = std::pair<aiBone *, unsigned int> ;
// ---------------------------------------------------------------------------
/** @brief Helper data structure for SceneCombiner::MergeBones.

View File

@@ -61,13 +61,14 @@ struct find_node_by_name_predicate {
/// @brief The default constructor.
find_node_by_name_predicate() = default;
std::string mName; ///< The name to find.
find_node_by_name_predicate(const std::string &name) :
mName(name) {
/// @brief Constructor with the predicate name
/// @param name The name.
explicit find_node_by_name_predicate(const std::string &name) : mName(name) {
// empty
}
std::string mName; ///< The name to find.
bool operator()(pugi::xml_node node) const {
return node.name() == mName;
}
@@ -78,6 +79,9 @@ struct find_node_by_name_predicate {
template <class TNodeType>
struct NodeConverter {
public:
/// @brief Will convert the attribute from the node to an int.
/// @param node The XML-node.
/// @param attribName The name of the attribute.
static int to_int(TNodeType &node, const char *attribName) {
ai_assert(nullptr != attribName);
return node.attribute(attribName).to_int();

View File

@@ -57,12 +57,24 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
namespace Assimp {
/// @brief This class implements a ZIP archive base file system.
class ZipArchiveIOSystem : public IOSystem {
public:
//! Open a Zip using the proffered IOSystem
/// @brief The class constructor with the zip-archive name.
/// @param pIOHandler The io handler
/// @param pFilename The archive name
/// @param pMode The access state
ZipArchiveIOSystem(IOSystem* pIOHandler, const char *pFilename, const char* pMode = "r");
/// @brief The class constructor with the zip-archive name.
/// @param pIOHandler The io handler
/// @param pFilename The archive name
/// @param pMode The access state
ZipArchiveIOSystem(IOSystem* pIOHandler, const std::string& rFilename, const char* pMode = "r");
/// @brief The class destructor.
~ZipArchiveIOSystem() override;
bool Exists(const char* pFilename) const override;
char getOsSeparator() const override;
IOStream* Open(const char* pFilename, const char* pMode = "rb") override;

View File

@@ -5,8 +5,6 @@ Open Asset Import Library (assimp)
Copyright (c) 2006-2025, assimp team
All rights reserved.
Redistribution and use of this software in source and binary forms,
@@ -48,9 +46,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
class utLineSplitter : public ::testing::Test {
// empty
};
class utLineSplitter : public ::testing::Test {};
TEST_F(utLineSplitter, tokenizetest) {
DefaultIOSystem fs;

View File

@@ -49,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
using namespace Assimp;
static const float VertComponents[24 * 3] = {
static constexpr float VertComponents[24 * 3] = {
-0.500000, 0.500000, 0.500000,
-0.500000, 0.500000, -0.500000,
-0.500000, -0.500000, -0.500000,
@@ -76,7 +76,7 @@ static const float VertComponents[24 * 3] = {
0.500000, -0.500000, 0.500000f
};
static const char *ObjModel =
static constexpr char ObjModel[] =
"o 1\n"
"\n"
"# Vertex list\n"
@@ -103,7 +103,7 @@ static const char *ObjModel =
"\n"
"# End of file\n";
static const char *ObjModel_Issue1111 =
static constexpr char ObjModel_Issue1111[] =
"o 1\n"
"\n"
"# Vertex list\n"
@@ -408,7 +408,7 @@ TEST_F(utObjImportExport, homogeneous_coordinates_divide_by_zero_Test) {
EXPECT_EQ(nullptr, scene);
}
TEST_F(utObjImportExport, 0based_array_Test) {
TEST_F(utObjImportExport, zero_based_array_Test) {
static const char *curObjModel =
"v -0.500000 0.000000 0.400000\n"
"v -0.500000 0.000000 -0.800000\n"

View File

@@ -38,22 +38,19 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
---------------------------------------------------------------------------
*/
#ifndef ASSIMP_BUILD_NO_OBJ_IMPORTER
#include "AssetLib/Obj/ObjFileParser.h"
#include "AssetLib/Obj/ObjTools.h"
#include "UnitTestPCH.h"
using namespace ::Assimp;
class utObjTools : public ::testing::Test {
// empty
};
class utObjTools : public ::testing::Test {};
class TestObjFileParser : public ObjFileParser {
public:
TestObjFileParser() :
ObjFileParser() {
// empty
}
TestObjFileParser() = default;
~TestObjFileParser() = default;
@@ -84,7 +81,7 @@ TEST_F(utObjTools, skipDataLine_TwoLines_Success) {
buffer.resize(data.size());
::memcpy(&buffer[0], &data[0], data.size());
test_parser.setBuffer(buffer);
static const size_t Size = 4096UL;
static constexpr size_t Size = 4096UL;
char data_buffer[Size];
test_parser.testCopyNextWord(data_buffer, Size);
@@ -112,3 +109,5 @@ TEST_F(utObjTools, countComponents_TwoLines_Success) {
size_t numComps = test_parser.testGetNumComponentsInDataDefinition();
EXPECT_EQ(3U, numComps);
}
#endif // ASSIMP_BUILD_NO_OBJ_IMPORTER

View File

@@ -52,22 +52,16 @@ using namespace ::Assimp;
class utSIBImporter : public AbstractImportExportBase {
public:
virtual bool importerTest() {
Assimp::Importer importer;
Importer importer;
const aiScene *scene = importer.ReadFile(ASSIMP_TEST_MODELS_DIR "/SIB/heffalump.sib", aiProcess_ValidateDataStructure);
return nullptr != scene;
}
};
TEST_F(utSIBImporter, createTest) {
bool ok(true);
try {
SIBImporter myImporter;
} catch (...) {
ok = false;
}
EXPECT_TRUE(ok);
}
TEST_F(utSIBImporter, importTest) {
#ifdef ASSIMP_BUILD_NO_SIB_IMPORTER
EXPECT_FALSE(importerTest());
#else
EXPECT_TRUE(importerTest());
#endif
}

View File

@@ -56,18 +56,12 @@ public:
}
};
TEST_F(utSMDImporter, createTest) {
bool ok(true);
try {
SMDImporter myImporter;
} catch (...) {
ok = false;
}
EXPECT_TRUE(ok);
}
TEST_F(utSMDImporter, importTest) {
#ifndef ASSIMP_BUILD_NO_SMD_IMPORTER
EXPECT_TRUE(importerTest());
#else
EXPECT_FALSE(importerTest());
#endif
}
TEST_F(utSMDImporter, issue_899_Texture_garbage_at_end_of_string_Test) {