Merge branch 'master' into bugfix/fix_linkage_no_importers_issue-5971
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 */
|
||||
|
||||
@@ -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__) \
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user