Merge branch 'master' into bugfix/fix_linkage_no_importers_issue-5971

This commit is contained in:
Kim Kulling
2025-11-16 17:07:58 +01:00
committed by GitHub
26 changed files with 423 additions and 338 deletions

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

@@ -49,7 +49,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <set>
//
#if _MSC_VER > 1500 || (defined __GNUC___)
#if _MSC_VER > 1500 || (defined __GNUC__)
# define ASSIMP_FBX_USE_UNORDERED_MULTIMAP
# else
# define fbx_unordered_map map

View File

@@ -58,7 +58,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# pragma warning(disable : 4127 4456 4245 4512 )
#endif // _MSC_VER
#if _MSC_VER > 1500 || (defined __GNUC___)
#if _MSC_VER > 1500 || (defined __GNUC__)
# define ASSIMP_STEP_USE_UNORDERED_MULTIMAP
#else
# define step_unordered_map map

View File

@@ -63,7 +63,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <memory>
//
#if _MSC_VER > 1500 || (defined __GNUC___)
#if _MSC_VER > 1500 || (defined __GNUC__)
# define ASSIMP_STEP_USE_UNORDERED_MULTIMAP
# else
# define step_unordered_map map

View File

@@ -83,7 +83,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#endif
#if _MSC_VER > 1500 || (defined __GNUC___)
#if _MSC_VER > 1500 || (defined __GNUC__)
# define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
# else
# define gltf_unordered_map map

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

@@ -64,7 +64,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <algorithm>
#include <list>
#include <map>
#include <unordered_map>
#include <set>
#include <stdexcept>
#include <string>
@@ -95,7 +95,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# define ai_assert
#endif
#if _MSC_VER > 1500 || (defined __GNUC___)
#if _MSC_VER > 1500 || (defined __GNUC__)
# define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
#else
# define gltf_unordered_map map
@@ -1266,9 +1266,8 @@ private:
size_t mSceneLength;
size_t mBodyOffset;
size_t mBodyLength;
IdMap mUsedIds;
std::map<std::string, int, std::less<>> mUsedNamesMap;
Ref<Buffer> mBodyBuffer;
std::unordered_map<std::string, int> lastUsedID;
};
inline std::string getContextForErrorMessages(const std::string &id, const std::string &name) {

View File

@@ -438,7 +438,6 @@ unsigned int LazyDict<T>::Remove(const char *id) {
const unsigned int index = objIt->second;
mAsset.mUsedIds[id] = false;
mObjsById.erase(id);
mObjsByOIndex.erase(index);
delete mObjs[index];
@@ -472,7 +471,6 @@ unsigned int LazyDict<T>::Remove(const char *id) {
template <class T>
Ref<T> LazyDict<T>::Retrieve(unsigned int i) {
typename Dict::iterator it = mObjsByOIndex.find(i);
if (it != mObjsByOIndex.end()) { // already created?
return Ref<T>(mObjs, it->second);
@@ -540,16 +538,11 @@ Ref<T> LazyDict<T>::Add(T *obj) {
mObjs.push_back(obj);
mObjsByOIndex[obj->oIndex] = idx;
mObjsById[obj->id] = idx;
mAsset.mUsedIds[obj->id] = true;
return Ref<T>(mObjs, idx);
}
template <class T>
Ref<T> LazyDict<T>::Create(const char *id) {
Asset::IdMap::iterator it = mAsset.mUsedIds.find(id);
if (it != mAsset.mUsedIds.end()) {
throw DeadlyImportError("GLTF: two objects with the same ID exist");
}
T *inst = new T();
unsigned int idx = unsigned(mObjs.size());
inst->id = id;
@@ -565,11 +558,12 @@ inline Buffer::Buffer() :
byteLength(0),
type(Type_arraybuffer),
EncodedRegion_Current(nullptr),
mIsSpecial(false) {}
mIsSpecial(false) {
// empty
}
inline Buffer::~Buffer() {
for (SEncodedRegion *reg : EncodedRegion_List)
delete reg;
for (SEncodedRegion *reg : EncodedRegion_List) delete reg;
}
inline const char *Buffer::TranslateId(Asset & /*r*/, const char *id) {
@@ -693,7 +687,6 @@ inline void Buffer::EncodedRegion_SetCurrent(const std::string &pID) {
}
inline bool Buffer::ReplaceData(const size_t pBufferData_Offset, const size_t pBufferData_Count, const uint8_t *pReplace_Data, const size_t pReplace_Count) {
if ((pBufferData_Count == 0) || (pReplace_Count == 0) || (pReplace_Data == nullptr)) {
return false;
}
@@ -809,8 +802,7 @@ inline uint8_t *BufferView::GetPointerAndTailSize(size_t accOffset, size_t& outT
}
}
if (offset >= buffer->byteLength)
{
if (offset >= buffer->byteLength) {
outTailSize = 0;
return nullptr;
}
@@ -2206,29 +2198,27 @@ inline IOStream *Asset::OpenFile(const std::string &path, const char *mode, bool
inline std::string Asset::FindUniqueID(const std::string &str, const char *suffix) {
std::string id = str;
if (!id.empty()) {
if (mUsedIds.find(id) == mUsedIds.end()){
mUsedNamesMap[id] = 0;
int n = 1;
if(!id.empty()) {
n = lastUsedID[id];
if(!n) {
lastUsedID[id] = n+1;
return id;
}
id += "_";
}
id += suffix;
Asset::IdMap::iterator it = mUsedIds.find(id);
if (it == mUsedIds.end()) {
mUsedNamesMap[id] = 0;
return id;
if(suffix) {
id += suffix;
n = lastUsedID[id];
if(!n) {
lastUsedID[id] = n+1;
return id;
}
}
auto key = id;
id += "_" + std::to_string(mUsedNamesMap[key]);
mUsedNamesMap[key] = mUsedNamesMap[key] + 1;
return id;
lastUsedID[id] = n+1;
return id + "_" + std::to_string(n-1);
}
#if _MSC_VER

View File

@@ -67,7 +67,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# define ai_assert
#endif
#if _MSC_VER > 1500 || (defined __GNUC___)
#if _MSC_VER > 1500 || (defined __GNUC__)
# define ASSIMP_GLTF_USE_UNORDERED_MULTIMAP
#else
# define gltf_unordered_map map

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;