From 408b5053a44652a2a8eebddc672f394f01df25d8 Mon Sep 17 00:00:00 2001 From: bearbit Date: Tue, 3 Aug 2021 20:18:14 +0300 Subject: [PATCH 01/16] update LWO importer(available lwo3) --- code/AssetLib/LWO/LWOFileData.h | 78 ++++++++ code/AssetLib/LWO/LWOLoader.cpp | 222 +++++++++++++++++++-- code/AssetLib/LWO/LWOLoader.h | 32 +++ code/AssetLib/LWO/LWOMaterial.cpp | 319 +++++++++++++++++++++++++++++- code/Common/IFF.h | 29 +++ 5 files changed, 665 insertions(+), 15 deletions(-) diff --git a/code/AssetLib/LWO/LWOFileData.h b/code/AssetLib/LWO/LWOFileData.h index 93ac1a236..6dcd2adfb 100644 --- a/code/AssetLib/LWO/LWOFileData.h +++ b/code/AssetLib/LWO/LWOFileData.h @@ -64,6 +64,7 @@ namespace LWO { #define AI_LWO_FOURCC_LWOB AI_IFF_FOURCC('L', 'W', 'O', 'B') #define AI_LWO_FOURCC_LWO2 AI_IFF_FOURCC('L', 'W', 'O', '2') +#define AI_LWO_FOURCC_LWO3 AI_IFF_FOURCC('L', 'W', 'O', '3') #define AI_LWO_FOURCC_LXOB AI_IFF_FOURCC('L', 'X', 'O', 'B') // chunks specific to the LWOB format @@ -248,6 +249,57 @@ namespace LWO { #define AI_LWO_SPOT AI_IFF_FOURCC('S', 'P', 'O', 'T') #define AI_LWO_PICK AI_IFF_FOURCC('P', 'I', 'C', 'K') +// Surface Part +#define AI_LWO_NODS AI_IFF_FOURCC('N', 'O', 'D', 'S') +#define AI_LWO_NNDS AI_IFF_FOURCC('N', 'N', 'D', 'S') +#define AI_LWO_NTAG AI_IFF_FOURCC('N', 'T', 'A', 'G') +#define AI_LWO_NRNM AI_IFF_FOURCC('N', 'R', 'N', 'M') +#define AI_LWO_NRME AI_IFF_FOURCC('N', 'R', 'M', 'E') +#define AI_LWO_NDTA AI_IFF_FOURCC('N', 'D', 'T', 'A') +#define AI_LWO_ATTR AI_IFF_FOURCC('A', 'T', 'T', 'R') +#define AI_LWO_VERS AI_IFF_FOURCC('V', 'E', 'R', 'S') +#define AI_LWO_ENUM AI_IFF_FOURCC('E', 'N', 'U', 'M') +#define AI_LWO_ENTR AI_IFF_FOURCC('E', 'N', 'T', 'R') +#define AI_LWO_NAME AI_IFF_FOURCC('N', 'A', 'M', 'E') +#define AI_LWO_FLAG AI_IFF_FOURCC('F', 'L', 'A', 'G') +#define AI_LWO_TAG AI_IFF_FOURCC('T', 'A', 'G', ' ') +#define AI_LWO_VALU AI_IFF_FOURCC('V', 'A', 'L', 'U') +#define AI_LWO_IBGC AI_IFF_FOURCC('I', 'B', 'G', 'C') +#define AI_LWO_IOPC AI_IFF_FOURCC('I', 'O', 'P', 'C') +#define AI_LWO_IIMG AI_IFF_FOURCC('I', 'I', 'M', 'G') +#define AI_LWO_TXTR AI_IFF_FOURCC('T', 'X', 'T', 'R') + +#define AI_LWO_IFAL AI_IFF_FOURCC('I', 'F', 'A', 'L') +#define AI_LWO_ISCL AI_IFF_FOURCC('I', 'S', 'C', 'L') +#define AI_LWO_IPOS AI_IFF_FOURCC('I', 'P', 'O', 'S') +#define AI_LWO_IROT AI_IFF_FOURCC('I', 'R', 'O', 'T') +#define AI_LWO_IBMP AI_IFF_FOURCC('I', 'B', 'M', 'P') +#define AI_LWO_IUTD AI_IFF_FOURCC('I', 'U', 'T', 'D') +#define AI_LWO_IVTD AI_IFF_FOURCC('I', 'V', 'T', 'D') + +#define AI_LWO_IPIX AI_IFF_FOURCC('I', 'P', 'I', 'X') +#define AI_LWO_IMIP AI_IFF_FOURCC('I', 'M', 'I', 'P') +#define AI_LWO_IMOD AI_IFF_FOURCC('I', 'M', 'O', 'D') +#define AI_LWO_AMOD AI_IFF_FOURCC('A', 'M', 'O', 'D') +#define AI_LWO_IINV AI_IFF_FOURCC('I', 'I', 'N', 'V') +#define AI_LWO_INCR AI_IFF_FOURCC('I', 'N', 'C', 'R') +#define AI_LWO_IAXS AI_IFF_FOURCC('I', 'A', 'X', 'S') +#define AI_LWO_IFOT AI_IFF_FOURCC('I', 'F', 'O', 'T') +#define AI_LWO_ITIM AI_IFF_FOURCC('I', 'T', 'I', 'M') +#define AI_LWO_IWRL AI_IFF_FOURCC('I', 'W', 'R', 'L') +#define AI_LWO_IUTI AI_IFF_FOURCC('I', 'U', 'T', 'I') +#define AI_LWO_IINX AI_IFF_FOURCC('I', 'I', 'N', 'X') +#define AI_LWO_IINY AI_IFF_FOURCC('I', 'I', 'N', 'Y') +#define AI_LWO_IINZ AI_IFF_FOURCC('I', 'I', 'N', 'Z') +#define AI_LWO_IREF AI_IFF_FOURCC('I', 'R', 'E', 'F') +#define AI_LWO_IMST AI_IFF_FOURCC('I', 'M', 'S', 'T') +#define AI_LWO_VPVL AI_IFF_FOURCC('V', 'P', 'V', 'L') +#define AI_LWO_VPRM AI_IFF_FOURCC('V', 'P', 'R', 'M') +#define AI_LWO_IMAP AI_IFF_FOURCC('I', 'M', 'A', 'P') +#define AI_LWO_IUVI AI_IFF_FOURCC('I', 'U', 'V', 'I') +#define AI_LWO_IUTL AI_IFF_FOURCC('I', 'U', 'T', 'L') +#define AI_LWO_IVTL AI_IFF_FOURCC('I', 'V', 'T', 'L') + // MODO extension - per-vertex normal vectors #define AI_LWO_MODO_NORM AI_IFF_FOURCC('N', 'O', 'R', 'M') @@ -494,6 +546,7 @@ struct Shader { typedef std::list TextureList; typedef std::list ShaderList; +//typedef std::list NodeList; // --------------------------------------------------------------------------- /** \brief Data structure for a LWO file surface (= material) @@ -555,6 +608,31 @@ struct Surface { float mAdditiveTransparency; }; +// --------------------------------------------------------------------------- +/** \brief Data structure for a LWO node + */ +struct Node { + // Name of node + std::string mName; + + // RefName of node + std::string mRefName; + + // Ref FileName + std::string fileName; +}; + +struct NodeAttribute { + //! Color of the surface + aiColor3D mColor; + + //! true for two-sided materials + bool bDoubleSided; + + //! Various material parameters + float mDiffuseValue, mSpecularValue, mTransparency, mGlossiness, mLuminosity, mColorHighlights; +}; + // --------------------------------------------------------------------------- #define AI_LWO_VALIDATE_CHUNK_LENGTH(length, name, size) \ if (length < size) { \ diff --git a/code/AssetLib/LWO/LWOLoader.cpp b/code/AssetLib/LWO/LWOLoader.cpp index bc62152c5..8ade75409 100644 --- a/code/AssetLib/LWO/LWOLoader.cpp +++ b/code/AssetLib/LWO/LWOLoader.cpp @@ -82,6 +82,7 @@ static const aiImporterDesc desc = { // Constructor to be privately used by Importer LWOImporter::LWOImporter() : mIsLWO2(), + mIsLWO3(), mIsLXOB(), mLayers(), mCurLayer(), @@ -190,16 +191,19 @@ void LWOImporter::InternReadFile(const std::string &pFile, mCurLayer->mIndex = (uint16_t) -1; // old lightwave file format (prior to v6) + mIsLWO2 = false; + mIsLWO3 = false; + mIsLXOB = false; + if (AI_LWO_FOURCC_LWOB == fileType) { ASSIMP_LOG_INFO("LWO file format: LWOB (<= LightWave 5.5)"); - mIsLWO2 = false; - mIsLXOB = false; LoadLWOBFile(); } else if (AI_LWO_FOURCC_LWO2 == fileType) { // New lightwave format - mIsLXOB = false; ASSIMP_LOG_INFO("LWO file format: LWO2 (>= LightWave 6)"); + } else if ( AI_LWO_FOURCC_LWO3 == fileType ) { + ASSIMP_LOG_INFO("LWO file format: LWO3 (>= LightWave 2018)"); } else if (AI_LWO_FOURCC_LXOB == fileType) { // MODO file format mIsLXOB = true; @@ -215,8 +219,13 @@ void LWOImporter::InternReadFile(const std::string &pFile, throw DeadlyImportError("Unknown LWO sub format: ", szBuff); } - if (AI_LWO_FOURCC_LWOB != fileType) { - mIsLWO2 = true; + if (AI_LWO_FOURCC_LWOB != fileType) { // + if( AI_LWO_FOURCC_LWO3 == fileType ) { + mIsLWO3 = true; + } else { + mIsLWO2 = true; + } + LoadLWO2File(); // The newer lightwave format allows the user to configure the @@ -450,6 +459,7 @@ void LWOImporter::InternReadFile(const std::string &pFile, // The RemoveRedundantMaterials step will clean this up later pScene->mMaterials = new aiMaterial *[pScene->mNumMaterials = (unsigned int)mSurfaces->size()]; + for (unsigned int mat = 0; mat < pScene->mNumMaterials; ++mat) { aiMaterial *pcMat = new aiMaterial(); pScene->mMaterials[mat] = pcMat; @@ -695,7 +705,7 @@ void LWOImporter::ResolveClips() { // ------------------------------------------------------------------------------------------------ void LWOImporter::AdjustTexturePath(std::string &out) { // --- this function is used for both LWO2 and LWOB - if (!mIsLWO2 && ::strstr(out.c_str(), "(sequence)")) { + if (!mIsLWO2 && !mIsLWO3 && ::strstr(out.c_str(), "(sequence)")) { // remove the (sequence) and append 000 ASSIMP_LOG_INFO("LWOB: Sequence of animated texture found. It will be ignored"); @@ -738,7 +748,7 @@ void LWOImporter::LoadLWOPoints(unsigned int length) { throw DeadlyImportError("LWO2: Points chunk length is not multiple of vertexLen (12)"); } unsigned int regularSize = (unsigned int)mCurLayer->mTempPoints.size() + length / 12; - if (mIsLWO2) { + if (mIsLWO2 || mIsLWO3) { mCurLayer->mTempPoints.reserve(regularSize + (regularSize >> 2u)); mCurLayer->mTempPoints.resize(regularSize); @@ -1163,6 +1173,76 @@ void LWOImporter::LoadLWO2Clip(unsigned int length) { } } +void LWOImporter::LoadLWO3Clip(unsigned int length) { + AI_LWO_VALIDATE_CHUNK_LENGTH(length, CLIP, 12); + + mClips.push_back(LWO::Clip()); + LWO::Clip &clip = mClips.back(); + + // first - get the index of the clip + clip.idx = GetU4(); + + IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer); + switch (head.type) { + case AI_LWO_STIL: + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, STIL, 1); + + // "Normal" texture + GetS0(clip.path, head.length); + clip.type = Clip::STILL; + break; + + case AI_LWO_ISEQ: + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, ISEQ, 16); + // Image sequence. We'll later take the first. + { + uint8_t digits = GetU1(); + mFileBuffer++; + int16_t offset = GetU2(); + mFileBuffer += 4; + int16_t start = GetU2(); + mFileBuffer += 4; + + std::string s; + std::ostringstream ss; + GetS0(s, head.length); + + head.length -= (uint16_t)s.length() + 1; + ss << s; + ss << std::setw(digits) << offset + start; + GetS0(s, head.length); + ss << s; + clip.path = ss.str(); + clip.type = Clip::SEQ; + } + break; + + case AI_LWO_STCC: + ASSIMP_LOG_WARN("LWO3: Color shifted images are not supported"); + break; + + case AI_LWO_ANIM: + ASSIMP_LOG_WARN("LWO3: Animated textures are not supported"); + break; + + case AI_LWO_XREF: + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, XREF, 4); + + // Just a cross-reference to another CLIp + clip.type = Clip::REF; + clip.clipRef = GetU4(); + break; + + case AI_LWO_NEGA: + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, NEGA, 2); + clip.negate = (0 != GetU2()); + break; + + default: + ASSIMP_LOG_WARN("LWO3: Encountered unknown CLIP sub-chunk"); + } +} + // ------------------------------------------------------------------------------------------------ // Load envelope description void LWOImporter::LoadLWO2Envelope(unsigned int length) { @@ -1273,6 +1353,104 @@ void LWOImporter::LoadLWO2Envelope(unsigned int length) { } } +void LWOImporter::LoadLWO3Envelope(unsigned int length) { + LE_NCONST uint8_t *const end = mFileBuffer + length; + AI_LWO_VALIDATE_CHUNK_LENGTH(length, ENVL, 4); + + mEnvelopes.push_back(LWO::Envelope()); + LWO::Envelope &envelope = mEnvelopes.back(); + + // Get the index of the envelope + envelope.index = ReadVSizedIntLWO2(mFileBuffer); + + // ... and read all blocks + while (true) { + if (mFileBuffer + 8 >= end) break; + LE_NCONST IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer); + + if (mFileBuffer + head.length > end) + throw DeadlyImportError("LWO3: Invalid envelope chunk length"); + + uint8_t *const next = mFileBuffer + head.length; + switch (head.type) { + // Type & representation of the envelope + case AI_LWO_TYPE: + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, TYPE, 4); + mFileBuffer++; // skip user format + + // Determine type of envelope + envelope.type = (LWO::EnvelopeType)*mFileBuffer; + ++mFileBuffer; + break; + + // precondition + case AI_LWO_PRE: + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, PRE, 4); + envelope.pre = (LWO::PrePostBehaviour)GetU2(); + break; + + // postcondition + case AI_LWO_POST: + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, POST, 4); + envelope.post = (LWO::PrePostBehaviour)GetU2(); + break; + + // keyframe + case AI_LWO_KEY: { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, KEY, 10); + + envelope.keys.push_back(LWO::Key()); + LWO::Key &key = envelope.keys.back(); + + key.time = GetF4(); + key.value = GetF4(); + break; + } + + // interval interpolation + case AI_LWO_SPAN: { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SPAN, 6); + if (envelope.keys.size() < 2) + ASSIMP_LOG_WARN("LWO3: Unexpected SPAN chunk"); + else { + LWO::Key &key = envelope.keys.back(); + switch (GetU4()) { + case AI_LWO_STEP: + key.inter = LWO::IT_STEP; + break; + case AI_LWO_LINE: + key.inter = LWO::IT_LINE; + break; + case AI_LWO_TCB: + key.inter = LWO::IT_TCB; + break; + case AI_LWO_HERM: + key.inter = LWO::IT_HERM; + break; + case AI_LWO_BEZI: + key.inter = LWO::IT_BEZI; + break; + case AI_LWO_BEZ2: + key.inter = LWO::IT_BEZ2; + break; + default: + ASSIMP_LOG_WARN("LWO3: Unknown interval interpolation mode"); + }; + + // todo ... read params + } + break; + } + + default: + ASSIMP_LOG_WARN("LWO3: Encountered unknown ENVL subchunk"); + break; + } + // regardless how much we did actually read, go to the next chunk + mFileBuffer = next; + } +} + // ------------------------------------------------------------------------------------------------ // Load file - master function void LWOImporter::LoadLWO2File() { @@ -1280,16 +1458,25 @@ void LWOImporter::LoadLWO2File() { LE_NCONST uint8_t *const end = mFileBuffer + fileSize; unsigned int iUnnamed = 0; + while (true) { if (mFileBuffer + sizeof(IFF::ChunkHeader) > end) break; - const IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer); + + IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer); + + int bufOffset = 0; + if( head.type == AI_IFF_FOURCC_FORM ) { // not chunk, it's a form + mFileBuffer -= 8; + head = IFF::LoadForm(mFileBuffer); + bufOffset = 4; + } if (mFileBuffer + head.length > end) { throw DeadlyImportError("LWO2: Chunk length points behind the file"); break; } uint8_t *const next = mFileBuffer + head.length; - + mFileBuffer += bufOffset; if (!head.length) { mFileBuffer = next; continue; @@ -1345,7 +1532,6 @@ void LWOImporter::LoadLWO2File() { break; } - // vertex list case AI_LWO_PNTS: { if (skip) @@ -1407,19 +1593,29 @@ void LWOImporter::LoadLWO2File() { // surface chunk case AI_LWO_SURF: { - LoadLWO2Surface(head.length); + if( mIsLWO3 ) + LoadLWO3Surface(head.length); + else + LoadLWO2Surface(head.length); + break; } // clip chunk case AI_LWO_CLIP: { - LoadLWO2Clip(head.length); + if( mIsLWO3 ) + LoadLWO3Clip(head.length); + else + LoadLWO2Clip(head.length); break; } // envelope chunk case AI_LWO_ENVL: { - LoadLWO2Envelope(head.length); + if( mIsLWO3 ) + LoadLWO3Envelope(head.length); + else + LoadLWO2Envelope(head.length); break; } } diff --git a/code/AssetLib/LWO/LWOLoader.h b/code/AssetLib/LWO/LWOLoader.h index 31911945f..c1c9ae99b 100644 --- a/code/AssetLib/LWO/LWOLoader.h +++ b/code/AssetLib/LWO/LWOLoader.h @@ -121,6 +121,8 @@ private: */ inline void GetS0(std::string& out,unsigned int max); inline float GetF4(); + inline float GetF8(); + inline uint64_t GetU8(); inline uint32_t GetU4(); inline uint16_t GetU2(); inline uint8_t GetU1(); @@ -137,6 +139,7 @@ private: * @param size Maximum size to be read, in bytes. */ void LoadLWO2Surface(unsigned int size); + void LoadLWO3Surface(unsigned int size); // ------------------------------------------------------------------- /** Loads a texture block from a LWO2 file. @@ -203,12 +206,23 @@ private: * @param length Size of the chunk */ void LoadLWO2Clip(unsigned int length); + void LoadLWO3Clip(unsigned int length); // ------------------------------------------------------------------- /** Load an envelope from an EVL chunk * @param length Size of the chunk */ void LoadLWO2Envelope(unsigned int length); + void LoadLWO3Envelope(unsigned int length); + + // ------------------------------------------------------------------- + /** Load an nodal blocks from surface form + * @param length Size of the chunk + */ + void LoadNodalBlocks(unsigned int length); + void LoadNodes(unsigned int length); + void LoadNodeTag(unsigned int length); + void LoadNodeData(unsigned int length); // ------------------------------------------------------------------- /** Count vertices and faces in a LWOB/LWO2 file @@ -356,6 +370,8 @@ protected: /** true if the file is a LXOB file*/ bool mIsLXOB; + bool mIsLWO3; + /** Temporary list of layers from the file */ LayerList* mLayers; @@ -411,6 +427,22 @@ float LWOImporter::GetF4() { return f; } +inline float LWOImporter::GetF8() { + double f; + ::memcpy(&f, mFileBuffer, 8); + mFileBuffer += 8; + AI_LSWAP8(f); + return (float)f; +} + +inline uint64_t LWOImporter::GetU8() { + uint64_t f; + ::memcpy(&f, mFileBuffer, 8); + mFileBuffer += 8; + AI_LSWAP8(f); + return f; +} + // ------------------------------------------------------------------------------------------------ inline uint32_t LWOImporter::GetU4() { diff --git a/code/AssetLib/LWO/LWOMaterial.cpp b/code/AssetLib/LWO/LWOMaterial.cpp index 178f24265..82ea9e4ca 100644 --- a/code/AssetLib/LWO/LWOMaterial.cpp +++ b/code/AssetLib/LWO/LWOMaterial.cpp @@ -159,7 +159,7 @@ bool LWOImporter::HandleTextures(aiMaterial *pcMat, const TextureList &in, aiTex // The older LWOB format does not use indirect references to clips. // The file name of a texture is directly specified in the tex chunk. - if (mIsLWO2) { + if (mIsLWO2 || mIsLWO3) { // find the corresponding clip (take the last one if multiple // share the same index) ClipList::iterator end = mClips.end(), candidate = end; @@ -270,7 +270,7 @@ void LWOImporter::ConvertMaterial(const LWO::Surface &surf, aiMaterial *pcMat) { aiShadingMode m; if (surf.mSpecularValue && surf.mGlossiness) { float fGloss; - if (mIsLWO2) { + if (mIsLWO2 || mIsLWO3) { fGloss = std::pow(surf.mGlossiness * ai_real(10.0) + ai_real(2.0), ai_real(2.0)); } else { if (16.0 >= surf.mGlossiness) @@ -688,6 +688,256 @@ void LWOImporter::LoadLWO2ShaderBlock(LE_NCONST IFF::SubChunkHeader * /*head*/, surf.mShaders.push_back(shader); } +// ------------------------------------------------------------------------------------------------ +void LWOImporter::LoadNodalBlocks(unsigned int size) { + LE_NCONST uint8_t *const end = mFileBuffer + size; + + while (true) { + if (mFileBuffer + 8 >= end) + break; + + IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer); + int bufOffset = 0; + if (head.type == AI_IFF_FOURCC_FORM) { // not chunk, it's a form + mFileBuffer -= 8; + head = IFF::LoadForm(mFileBuffer); + bufOffset = 4; + } + + if (mFileBuffer + head.length > end) { + throw DeadlyImportError("LWO3: cannot read length; LoadNodalBlocks"); + } + int node_idx = 0; + uint8_t *const next = mFileBuffer + head.length; + mFileBuffer += bufOffset; + switch (head.type) { + case AI_LWO_NNDS: + node_idx++; + LoadNodes(head.length); + break; + } + + mFileBuffer = next; + } +} + +// ------------------------------------------------------------------------------------------------ +void LWOImporter::LoadNodes(unsigned int size) { + LE_NCONST uint8_t *const end = mFileBuffer + size; + + while (true) { + if (mFileBuffer + 8 >= end) + break; + + IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer); + int bufOffset = 0; + if (head.type == AI_IFF_FOURCC_FORM) { // not chunk, it's a form + mFileBuffer -= 8; + head = IFF::LoadForm(mFileBuffer); + bufOffset = 4; + } + + if (mFileBuffer + head.length > end) { + throw DeadlyImportError("LWO3: cannot read length; LoadNodes"); + } + + uint8_t *const next = mFileBuffer + head.length; + mFileBuffer += bufOffset; + switch (head.type) { + case AI_LWO_NTAG: + LoadNodeTag(head.length); + break; + } + + mFileBuffer = next; + } +} + +// ------------------------------------------------------------------------------------------------ +void LWOImporter::LoadNodeTag(unsigned int size) { + LE_NCONST uint8_t *const end = mFileBuffer + size; + + while (true) { + if (mFileBuffer + 8 >= end) + break; + + IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer); + int bufOffset = 0; + if (head.type == AI_IFF_FOURCC_FORM) { // not chunk, it's a form + mFileBuffer -= 8; + head = IFF::LoadForm(mFileBuffer); + bufOffset = 4; + } + + if (mFileBuffer + head.length > end) { + throw DeadlyImportError("LWO3: cannot read length; LoadNodeTag"); + } + + uint8_t *const next = mFileBuffer + head.length; + mFileBuffer += bufOffset; + + switch (head.type) { + case AI_LWO_NDTA: + LoadNodeData(head.length); + break; + } + + mFileBuffer = next; + } +} + +// ------------------------------------------------------------------------------------------------ +void LWOImporter::LoadNodeData(unsigned int size) { + LE_NCONST uint8_t *const end = mFileBuffer + size; + + LWO::Surface &surf = mSurfaces->back(); + + while (true) { + if (mFileBuffer + 8 >= end) + break; + + IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer); + int bufOffset = 0; + if (head.type == AI_IFF_FOURCC_FORM) { // not chunk, it's a form + mFileBuffer -= 8; + head = IFF::LoadForm(mFileBuffer); + bufOffset = 4; + } + + if (mFileBuffer + head.length > end) { + throw DeadlyImportError("LWO3: INVALID LENGTH; LoadNodeData"); + } + + uint8_t *const next = mFileBuffer + head.length; + mFileBuffer += bufOffset; + switch (head.type) { + case AI_LWO_VERS: + case AI_LWO_ENUM: + case AI_LWO_IBGC: + case AI_LWO_IOPC: + case AI_LWO_IIMG: + case AI_LWO_TXTR: + case AI_LWO_IFAL: + case AI_LWO_ISCL: + case AI_LWO_IPOS: + case AI_LWO_IROT: + case AI_LWO_IBMP: + case AI_LWO_IUTD: + case AI_LWO_IVTD: + + case AI_LWO_IPIX: + case AI_LWO_IMIP: + case AI_LWO_IMOD: + case AI_LWO_AMOD: + case AI_LWO_IINV: + case AI_LWO_INCR: + case AI_LWO_IAXS: + case AI_LWO_IFOT: + case AI_LWO_ITIM: + case AI_LWO_IWRL: + case AI_LWO_IUTI: + case AI_LWO_IUVI: + case AI_LWO_IINX: + case AI_LWO_IINY: + case AI_LWO_IINZ: + case AI_LWO_IREF: + case AI_LWO_IMST: + case AI_LWO_IMAP: + case AI_LWO_IUTL: + case AI_LWO_IVTL: + case AI_LWO_VPVL: + case AI_LWO_VPRM: + mFileBuffer = next; + break; + case AI_LWO_ENTR: + std::string attrName; + + while (true) { + if (mFileBuffer + 8 >= next) + break; + + IFF::ChunkHeader head1 = IFF::LoadChunk(mFileBuffer); + int bufOffset1 = 0; + if (head1.type == AI_IFF_FOURCC_FORM) { // not chunk, it's a form + mFileBuffer -= 8; + head1 = IFF::LoadForm(mFileBuffer); + bufOffset1 = 4; + } + + if (mFileBuffer + head1.length > end) { + throw DeadlyImportError("LWO3: cannot read length;"); + } + uint8_t *const next1 = mFileBuffer + head1.length; + mFileBuffer += bufOffset1; + + switch (head1.type) { + case AI_LWO_FLAG: + case AI_LWO_TAG: + mFileBuffer = next1; + break; + case AI_LWO_NAME: + GetS0(attrName, head1.length); + break; + case AI_LWO_VALU: + mFileBuffer += 8; + + std::string valueType; + GetS0(valueType, 8); + + if (valueType == "int") { + uint32_t value; + value = GetU4(); + } else if (valueType == "double") { + uint64_t value; + value = GetU8(); + } else if (valueType == "vparam") { + mFileBuffer += 24; + + float value; + value = GetF8(); + + if (attrName == "Diffuse") { + surf.mDiffuseValue = value; + } else if (attrName == "Specular") { + surf.mSpecularValue = value; + } else if (attrName == "Transparency") { + surf.mTransparency = value; + } else if (attrName == "Glossiness") { + surf.mGlossiness = value; + } else if (attrName == "Luminosity") { + surf.mLuminosity = value; + } else if (attrName == "Color Highlight") { + surf.mColorHighlights = value; + } else if (attrName == "Refraction Index") { + surf.mIOR = value; + } else if (attrName == "Bump Height") { + surf.mBumpIntensity = value; + } + } else if (valueType == "vparam3") { + mFileBuffer += 24; + + float value1, value2, value3; + value1 = GetF8(); + value2 = GetF8(); + value3 = GetF8(); + + if (attrName == "Color") { + surf.mColor.r = value1; + surf.mColor.g = value2; + surf.mColor.b = value3; + } + } + + mFileBuffer = next1; + break; + } + } + + break; + } + } +} + // ------------------------------------------------------------------------------------------------ void LWOImporter::LoadLWO2Surface(unsigned int size) { LE_NCONST uint8_t *const end = mFileBuffer + size; @@ -841,4 +1091,69 @@ void LWOImporter::LoadLWO2Surface(unsigned int size) { } } +void LWOImporter::LoadLWO3Surface(unsigned int size) { + mFileBuffer += 8; + LE_NCONST uint8_t *const end = mFileBuffer + size - 12; + + mSurfaces->push_back(LWO::Surface()); + LWO::Surface &surf = mSurfaces->back(); + + GetS0(surf.mName, size); + + // check whether this surface was derived from any other surface + std::string derived; + GetS0(derived, (unsigned int)(end - mFileBuffer)); + if (derived.length()) { + // yes, find this surface + for (SurfaceList::iterator it = mSurfaces->begin(), itEnd = mSurfaces->end() - 1; it != itEnd; ++it) { + if ((*it).mName == derived) { + // we have it ... + surf = *it; + derived.clear(); + break; + } + } + if (derived.size()) { + ASSIMP_LOG_WARN("LWO3: Unable to find source surface: ", derived); + } + } + while (true) { + if (mFileBuffer + 8 >= end) + break; + + IFF::ChunkHeader head = IFF::LoadChunk(mFileBuffer); + int bufOffset = 0; + if( head.type == AI_IFF_FOURCC_FORM ) { // not chunk, it's a form + mFileBuffer -= 8; + head = IFF::LoadForm(mFileBuffer); + bufOffset = 4; + } + + if (mFileBuffer + head.length > end) { + throw DeadlyImportError("LWO3: cannot read length; LoadLWO3Surface"); + } + + uint8_t *const next = mFileBuffer + head.length; + mFileBuffer += bufOffset; + switch (head.type) { + case AI_LWO_NODS: + LoadNodalBlocks(head.length); + break; + // polygon sidedness + case AI_LWO_SIDE: { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SIDE, 2); + surf.bDoubleSided = (3 == GetU2()); + break; + } + // maximum smoothing angle + case AI_LWO_SMAN: { + AI_LWO_VALIDATE_CHUNK_LENGTH(head.length, SMAN, 4); + surf.mMaximumSmoothAngle = std::fabs(GetF4()); + break; + } + } + mFileBuffer = next; + } +} + #endif // !! ASSIMP_BUILD_NO_X_IMPORTER diff --git a/code/Common/IFF.h b/code/Common/IFF.h index 91d7d4828..cf07f9833 100644 --- a/code/Common/IFF.h +++ b/code/Common/IFF.h @@ -35,6 +35,17 @@ struct SubChunkHeader uint16_t length; }; +///////////////////////////////////////////////////////////////////////////////// +//! Describes an IFF form header +///////////////////////////////////////////////////////////////////////////////// +struct FormHeader +{ + //! Length of the chunk data, in bytes + uint32_t length; + + //! Type of the chunk header - FourCC + uint32_t type; +}; #define AI_IFF_FOURCC(a,b,c,d) ((uint32_t) (((uint8_t)a << 24u) | \ ((uint8_t)b << 16u) | ((uint8_t)c << 8u) | ((uint8_t)d))) @@ -77,6 +88,24 @@ inline SubChunkHeader LoadSubChunk(uint8_t*& outFile) return head; } +///////////////////////////////////////////////////////////////////////////////// +//! Load a chunk header +//! @param outFile Pointer to the file data - points to the chunk data afterwards +//! @return Copy of the chunk header +///////////////////////////////////////////////////////////////////////////////// +inline ChunkHeader LoadForm(uint8_t*& outFile) +{ + ChunkHeader head; + outFile += 4; + ::memcpy(&head.length, outFile, 4); + outFile += 4; + ::memcpy(&head.type, outFile, 4); + + AI_LSWAP4(head.length); + AI_LSWAP4(head.type); + return head; +} + ///////////////////////////////////////////////////////////////////////////////// //! Read the file header and return the type of the file and its size //! @param outFile Pointer to the file data. The buffer must at From 64393053794be6b2ebee636b2bfaf8b7a2789f06 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Tue, 24 Aug 2021 20:53:55 +0200 Subject: [PATCH 02/16] Remove dead code --- code/AssetLib/LWO/LWOFileData.h | 1 - 1 file changed, 1 deletion(-) diff --git a/code/AssetLib/LWO/LWOFileData.h b/code/AssetLib/LWO/LWOFileData.h index 6dcd2adfb..88ba78812 100644 --- a/code/AssetLib/LWO/LWOFileData.h +++ b/code/AssetLib/LWO/LWOFileData.h @@ -546,7 +546,6 @@ struct Shader { typedef std::list TextureList; typedef std::list ShaderList; -//typedef std::list NodeList; // --------------------------------------------------------------------------- /** \brief Data structure for a LWO file surface (= material) From 2fdf52488fba296beae885b4b6e983de375a8236 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Tue, 23 Nov 2021 13:53:58 +0000 Subject: [PATCH 03/16] float and integer material property bool conversion All reading float and integer material property values as bool Zero => False Non-Zero => True --- include/assimp/material.inl | 41 +++++++++++++++++++++ test/unit/utMaterialSystem.cpp | 67 ++++++++++++++++++++++++++++++---- 2 files changed, 101 insertions(+), 7 deletions(-) diff --git a/include/assimp/material.inl b/include/assimp/material.inl index 693785c3c..1aec6d865 100644 --- a/include/assimp/material.inl +++ b/include/assimp/material.inl @@ -137,6 +137,47 @@ aiReturn aiMaterial::Get(const char* pKey,unsigned int type, return ret; } +// --------------------------------------------------------------------------- +// Specialisation for a single bool. +// Casts floating point and integer to bool +template <> +AI_FORCE_INLINE + aiReturn + aiMaterial::Get(const char *pKey, unsigned int type, + unsigned int idx, bool &pOut) const { + const aiMaterialProperty *prop; + const aiReturn ret = ::aiGetMaterialProperty(this, pKey, type, idx, + (const aiMaterialProperty **)&prop); + if (AI_SUCCESS == ret) { + + switch (prop->mType) { + // Type cannot be converted + default: return AI_FAILURE; + + case aiPTI_Buffer: { + // Native bool value storage + if (prop->mDataLength < sizeof(bool)) { + return AI_FAILURE; + } + ::memcpy(&pOut, prop->mData, sizeof(bool)); + } break; + + case aiPTI_Float: + case aiPTI_Double: + case aiPTI_Integer: { + // Read as integer and cast to bool + int value = 0; + if (AI_SUCCESS == ::aiGetMaterialInteger(this, pKey, type, idx, &value)) { + pOut = static_cast(value); + return AI_SUCCESS; + } + return AI_FAILURE; + } + } + } + return ret; +} + // --------------------------------------------------------------------------- AI_FORCE_INLINE aiReturn aiMaterial::Get(const char* pKey,unsigned int type, diff --git a/test/unit/utMaterialSystem.cpp b/test/unit/utMaterialSystem.cpp index 8db014d9c..9df64ae3b 100644 --- a/test/unit/utMaterialSystem.cpp +++ b/test/unit/utMaterialSystem.cpp @@ -125,13 +125,66 @@ TEST_F(MaterialSystemTest, testStringProperty) { } // ------------------------------------------------------------------------------------------------ -TEST_F(MaterialSystemTest, testMaterialNameAccess) { - aiMaterial *mat = new aiMaterial(); - EXPECT_NE(nullptr, mat); - - aiString name = mat->GetName(); +TEST_F(MaterialSystemTest, testDefaultMaterialName) { + aiString name = pcMat->GetName(); const int retValue(strncmp(name.C_Str(), AI_DEFAULT_MATERIAL_NAME, name.length)); EXPECT_EQ(0, retValue); - - delete mat; +} + +// ------------------------------------------------------------------------------------------------ +TEST_F(MaterialSystemTest, testBoolProperty) { + const bool valTrue = true; + const bool valFalse = false; + EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&valTrue, 1, "bool_true")); + EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&valFalse, 1, "bool_false")); + + bool read = false; + EXPECT_EQ(AI_SUCCESS, pcMat->Get("bool_true", 0, 0, read)); + EXPECT_TRUE(read) << "read true bool"; + EXPECT_EQ(AI_SUCCESS, pcMat->Get("bool_false", 0, 0, read)); + EXPECT_FALSE(read) << "read false bool"; +} + +// ------------------------------------------------------------------------------------------------ +TEST_F(MaterialSystemTest, testCastIntProperty) { + int value = 10; + EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "integer")); + value = 0; + EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "zero")); + + // To float + float valFloat = 0.0f; + EXPECT_EQ(AI_SUCCESS, pcMat->Get("integer", 0, 0, valFloat)); + EXPECT_EQ(10.0f, valFloat); + EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valFloat)); + EXPECT_EQ(0.0f, valFloat); + + // To bool + bool valBool = false; + EXPECT_EQ(AI_SUCCESS, pcMat->Get("integer", 0, 0, valBool)); + EXPECT_EQ(true, valBool); + EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valBool)); + EXPECT_EQ(false, valBool); +} + +// ------------------------------------------------------------------------------------------------ +TEST_F(MaterialSystemTest, testCastFloatProperty) { + float value = 150392.63f; + EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "float")); + value = 0; + EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "zero")); + + // To int + int valInt = 0.0f; + EXPECT_EQ(AI_SUCCESS, pcMat->Get("float", 0, 0, valInt)); + EXPECT_EQ(150392, valInt); + EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valInt)); + EXPECT_EQ(0, valInt); + + // To bool + bool valBool = false; + EXPECT_EQ(AI_SUCCESS, pcMat->Get("float", 0, 0, valBool)); + EXPECT_EQ(true, valBool); + EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valBool)); + EXPECT_EQ(false, valBool); } From 5143044cc84decd933bebd0a48b2c24e816b074a Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Tue, 23 Nov 2021 13:55:27 +0000 Subject: [PATCH 04/16] redefine AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS This key is deprecated but is used by Qt5 & Qt 6.2.1 QtQuick3D --- include/assimp/pbrmaterial.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/assimp/pbrmaterial.h b/include/assimp/pbrmaterial.h index b642a96e3..2103a31f0 100644 --- a/include/assimp/pbrmaterial.h +++ b/include/assimp/pbrmaterial.h @@ -61,7 +61,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLIC_FACTOR AI_MATKEY_METALLIC_FACTOR #define AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_ROUGHNESS_FACTOR AI_MATKEY_ROUGHNESS_FACTOR -//#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS "$mat.gltf.pbrSpecularGlossiness", 0, 0 +#define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS AI_MATKEY_GLOSSINESS_FACTOR #define AI_MATKEY_GLTF_PBRSPECULARGLOSSINESS_GLOSSINESS_FACTOR AI_MATKEY_GLOSSINESS_FACTOR // Use AI_MATKEY_SHADING_MODEL == aiShadingMode_Unlit instead From d18709b899de50f18d9d6ae7cb85f4233a715179 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Tue, 23 Nov 2021 14:15:32 +0000 Subject: [PATCH 05/16] Small float values should be true --- include/assimp/material.inl | 15 ++++++++++----- test/unit/utMaterialSystem.cpp | 28 ++++++++++++++++++++++++++++ 2 files changed, 38 insertions(+), 5 deletions(-) diff --git a/include/assimp/material.inl b/include/assimp/material.inl index 1aec6d865..b299892b0 100644 --- a/include/assimp/material.inl +++ b/include/assimp/material.inl @@ -163,16 +163,21 @@ AI_FORCE_INLINE } break; case aiPTI_Float: - case aiPTI_Double: - case aiPTI_Integer: { - // Read as integer and cast to bool - int value = 0; - if (AI_SUCCESS == ::aiGetMaterialInteger(this, pKey, type, idx, &value)) { + case aiPTI_Double: { + // Read as float and cast to bool + float value = 0.0f; + if (AI_SUCCESS == ::aiGetMaterialFloat(this, pKey, type, idx, &value)) { pOut = static_cast(value); return AI_SUCCESS; } return AI_FAILURE; } + case aiPTI_Integer: { + // Cast to bool + const int value = static_cast(*prop->mData); + pOut = static_cast(value); + return AI_SUCCESS; + } } } return ret; diff --git a/test/unit/utMaterialSystem.cpp b/test/unit/utMaterialSystem.cpp index 9df64ae3b..363a4b193 100644 --- a/test/unit/utMaterialSystem.cpp +++ b/test/unit/utMaterialSystem.cpp @@ -151,6 +151,8 @@ TEST_F(MaterialSystemTest, testCastIntProperty) { EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "integer")); value = 0; EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "zero")); + value = -1; + EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "negative")); // To float float valFloat = 0.0f; @@ -158,6 +160,8 @@ TEST_F(MaterialSystemTest, testCastIntProperty) { EXPECT_EQ(10.0f, valFloat); EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valFloat)); EXPECT_EQ(0.0f, valFloat); + EXPECT_EQ(AI_SUCCESS, pcMat->Get("negative", 0, 0, valFloat)); + EXPECT_EQ(-1.0f, valFloat); // To bool bool valBool = false; @@ -165,6 +169,8 @@ TEST_F(MaterialSystemTest, testCastIntProperty) { EXPECT_EQ(true, valBool); EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valBool)); EXPECT_EQ(false, valBool); + EXPECT_EQ(AI_SUCCESS, pcMat->Get("negative", 0, 0, valBool)); + EXPECT_EQ(true, valBool); } // ------------------------------------------------------------------------------------------------ @@ -188,3 +194,25 @@ TEST_F(MaterialSystemTest, testCastFloatProperty) { EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valBool)); EXPECT_EQ(false, valBool); } + +// ------------------------------------------------------------------------------------------------ +TEST_F(MaterialSystemTest, testCastSmallFloatProperty) { + float value = 0.0078125f; + EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "float")); + value = 0; + EXPECT_EQ(AI_SUCCESS, pcMat->AddProperty(&value, 1, "zero")); + + // To int + int valInt = 0.0f; + EXPECT_EQ(AI_SUCCESS, pcMat->Get("float", 0, 0, valInt)); + EXPECT_EQ(0, valInt); + EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valInt)); + EXPECT_EQ(0, valInt); + + // To bool + bool valBool = false; + EXPECT_EQ(AI_SUCCESS, pcMat->Get("float", 0, 0, valBool)); + EXPECT_EQ(true, valBool); + EXPECT_EQ(AI_SUCCESS, pcMat->Get("zero", 0, 0, valBool)); + EXPECT_EQ(false, valBool); +} From 62c9347985eb38cbbb68f31c0e636ac9f02691be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaroslav=20P=C5=99ibyl?= Date: Tue, 22 Feb 2022 01:32:41 +0100 Subject: [PATCH 06/16] fixed obj parsing with cstype --- code/AssetLib/Obj/ObjFileParser.cpp | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/code/AssetLib/Obj/ObjFileParser.cpp b/code/AssetLib/Obj/ObjFileParser.cpp index 2e998a815..f819f326a 100644 --- a/code/AssetLib/Obj/ObjFileParser.cpp +++ b/code/AssetLib/Obj/ObjFileParser.cpp @@ -117,6 +117,7 @@ void ObjFileParser::parseFile(IOStreamBuffer &streamBuffer) { unsigned int processed = 0; size_t lastFilePos(0); + bool insideCstype = false; std::vector buffer; while (streamBuffer.getNextDataLine(buffer, '\\')) { m_DataIt = buffer.begin(); @@ -131,6 +132,23 @@ void ObjFileParser::parseFile(IOStreamBuffer &streamBuffer) { m_progress->UpdateFileRead(processed, progressTotal); } + // handle cstype (http://paulbourke.net/dataformats/obj/) which contains parm property which is handled by the parser as fase, but is not + // cstype bspline + // deg 1 + // curv 0 4.4342367553943109 468085 ... + // parm u 0 0 0.39203731404307385 ... + // end + if (insideCstype) { + switch (*m_DataIt) { + case 'e': { + std::string name; + getNameNoSpace(m_DataIt, m_DataItEnd, name); + insideCstype = name != "end"; + } break; + } + goto pf_skip_line; + } + // parse line switch (*m_DataIt) { case 'v': // Parse a vertex texture coordinate @@ -219,6 +237,14 @@ void ObjFileParser::parseFile(IOStreamBuffer &streamBuffer) { getObjectName(); } break; + case 'c': + { + std::string name; + getNameNoSpace(m_DataIt, m_DataItEnd, name); + insideCstype = name == "cstype"; + goto pf_skip_line; + } break; + default: { pf_skip_line: m_DataIt = skipLine(m_DataIt, m_DataItEnd, m_uiLine); From 480d6fee2a8aa8b97a0d397e0b7ce829fe910245 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaroslav=20P=C5=99ibyl?= Date: Tue, 22 Feb 2022 01:46:47 +0100 Subject: [PATCH 07/16] cleanup --- code/AssetLib/Obj/ObjFileParser.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/code/AssetLib/Obj/ObjFileParser.cpp b/code/AssetLib/Obj/ObjFileParser.cpp index f819f326a..1786c0d9f 100644 --- a/code/AssetLib/Obj/ObjFileParser.cpp +++ b/code/AssetLib/Obj/ObjFileParser.cpp @@ -132,12 +132,7 @@ void ObjFileParser::parseFile(IOStreamBuffer &streamBuffer) { m_progress->UpdateFileRead(processed, progressTotal); } - // handle cstype (http://paulbourke.net/dataformats/obj/) which contains parm property which is handled by the parser as fase, but is not - // cstype bspline - // deg 1 - // curv 0 4.4342367553943109 468085 ... - // parm u 0 0 0.39203731404307385 ... - // end + // handle cstype section end (http://paulbourke.net/dataformats/obj/) if (insideCstype) { switch (*m_DataIt) { case 'e': { @@ -237,7 +232,7 @@ void ObjFileParser::parseFile(IOStreamBuffer &streamBuffer) { getObjectName(); } break; - case 'c': + case 'c': // handle cstype section start { std::string name; getNameNoSpace(m_DataIt, m_DataItEnd, name); From 8a6a1fc2df5022607835ccdef32783f0d02562b0 Mon Sep 17 00:00:00 2001 From: RichardTea <31507749+RichardTea@users.noreply.github.com> Date: Tue, 1 Mar 2022 12:12:07 +0000 Subject: [PATCH 08/16] Update AI_TEXTURE_TYPE_MAX Must be equal to the largest aiTextureType_XXX enum --- include/assimp/material.h | 2 +- test/unit/utMaterialSystem.cpp | 60 ++++++++++++++++++++++++++++++++++ 2 files changed, 61 insertions(+), 1 deletion(-) diff --git a/include/assimp/material.h b/include/assimp/material.h index 416dbc4a8..2ccd83763 100644 --- a/include/assimp/material.h +++ b/include/assimp/material.h @@ -331,7 +331,7 @@ enum aiTextureType { #endif }; -#define AI_TEXTURE_TYPE_MAX aiTextureType_UNKNOWN +#define AI_TEXTURE_TYPE_MAX aiTextureType_TRANSMISSION // ------------------------------------------------------------------------------- // Get a string for a given aiTextureType diff --git a/test/unit/utMaterialSystem.cpp b/test/unit/utMaterialSystem.cpp index 7b4560443..3016f8881 100644 --- a/test/unit/utMaterialSystem.cpp +++ b/test/unit/utMaterialSystem.cpp @@ -135,3 +135,63 @@ TEST_F(MaterialSystemTest, testMaterialNameAccess) { delete mat; } + +// ------------------------------------------------------------------------------------------------ +#if defined(_MSC_VER) +// Refuse to compile on Windows if any enum values are not explicitly handled in the switch +// TODO: Move this into assimp/Compiler as a macro and add clang/gcc versions so other code can use it +__pragma(warning(push)); +__pragma(warning(error : 4061)); // enumerator 'identifier' in switch of enum 'enumeration' is not explicitly handled by a case label +__pragma(warning(error : 4062)); // enumerator 'identifier' in switch of enum 'enumeration' is not handled +#endif + +TEST_F(MaterialSystemTest, testMaterialTextureTypeEnum) { + // Verify that AI_TEXTURE_TYPE_MAX equals the largest 'real' value in the enum + + int32_t maxTextureType = 0; + static constexpr int32_t bigNumber = 255; + EXPECT_GT(bigNumber, AI_TEXTURE_TYPE_MAX) << "AI_TEXTURE_TYPE_MAX too large for valid enum test, increase bigNumber"; + + // Loop until a value larger than any enum + for (int32_t i = 0; i < bigNumber; ++i) { + aiTextureType texType = static_cast(i); + switch (texType) { + default: break; +#ifndef SWIG + case _aiTextureType_Force32Bit: break; +#endif + // All the real values + case aiTextureType_NONE: + case aiTextureType_DIFFUSE: + case aiTextureType_SPECULAR: + case aiTextureType_AMBIENT: + case aiTextureType_EMISSIVE: + case aiTextureType_HEIGHT: + case aiTextureType_NORMALS: + case aiTextureType_SHININESS: + case aiTextureType_OPACITY: + case aiTextureType_DISPLACEMENT: + case aiTextureType_LIGHTMAP: + case aiTextureType_REFLECTION: + case aiTextureType_BASE_COLOR: + case aiTextureType_NORMAL_CAMERA: + case aiTextureType_EMISSION_COLOR: + case aiTextureType_METALNESS: + case aiTextureType_DIFFUSE_ROUGHNESS: + case aiTextureType_AMBIENT_OCCLUSION: + case aiTextureType_SHEEN: + case aiTextureType_CLEARCOAT: + case aiTextureType_TRANSMISSION: + case aiTextureType_UNKNOWN: + if (i > maxTextureType) + maxTextureType = i; + break; + } + } + + EXPECT_EQ(maxTextureType, AI_TEXTURE_TYPE_MAX) << "AI_TEXTURE_TYPE_MAX macro must be equal to the largest valid aiTextureType_XXX"; +} + +#if defined(_MSC_VER) +__pragma (warning(pop)) +#endif From 9b227fc262aa7a296b51cfbe10685d6a88136df3 Mon Sep 17 00:00:00 2001 From: youkeyao Date: Thu, 3 Mar 2022 01:01:34 +0800 Subject: [PATCH 09/16] Fix getting anisotropy in obj --- code/AssetLib/Obj/ObjFileMtlImporter.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/code/AssetLib/Obj/ObjFileMtlImporter.cpp b/code/AssetLib/Obj/ObjFileMtlImporter.cpp index 2441c17f2..bb70a5ed0 100644 --- a/code/AssetLib/Obj/ObjFileMtlImporter.cpp +++ b/code/AssetLib/Obj/ObjFileMtlImporter.cpp @@ -238,6 +238,7 @@ void ObjFileMtlImporter::load() { case 'a': // Anisotropy { + ++m_DataIt; getFloatValue(m_pModel->m_pCurrentMaterial->anisotropy); m_DataIt = skipLine(m_DataIt, m_DataItEnd, m_uiLine); } break; From 52008ec9892c4e5993ea8bcf647ef60dc11badb5 Mon Sep 17 00:00:00 2001 From: Sergio Acereda Date: Thu, 3 Mar 2022 15:42:23 +0100 Subject: [PATCH 10/16] Apply clang-format --- code/AssetLib/glTF2/glTF2Importer.cpp | 374 +++++++++++++------------- 1 file changed, 186 insertions(+), 188 deletions(-) diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index 1f4cafdda..a95e752d7 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -42,23 +42,23 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #if !defined(ASSIMP_BUILD_NO_GLTF_IMPORTER) && !defined(ASSIMP_BUILD_NO_GLTF2_IMPORTER) #include "AssetLib/glTF2/glTF2Importer.h" -#include "PostProcessing/MakeVerboseFormat.h" #include "AssetLib/glTF2/glTF2Asset.h" +#include "PostProcessing/MakeVerboseFormat.h" #if !defined(ASSIMP_BUILD_NO_EXPORT) #include "AssetLib/glTF2/glTF2AssetWriter.h" #endif #include +#include #include #include #include +#include #include #include #include #include -#include -#include #include #include @@ -111,7 +111,7 @@ const aiImporterDesc *glTF2Importer::GetInfo() const { return &desc; } -bool glTF2Importer::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig ) const { +bool glTF2Importer::CanRead(const std::string &filename, IOSystem *pIOHandler, bool checkSig) const { const std::string extension = GetExtension(filename); if (!checkSig && (extension != "gltf") && (extension != "glb")) { return false; @@ -127,16 +127,16 @@ bool glTF2Importer::CanRead(const std::string &filename, IOSystem *pIOHandler, b static inline aiTextureMapMode ConvertWrappingMode(SamplerWrap gltfWrapMode) { switch (gltfWrapMode) { - case SamplerWrap::Mirrored_Repeat: - return aiTextureMapMode_Mirror; + case SamplerWrap::Mirrored_Repeat: + return aiTextureMapMode_Mirror; - case SamplerWrap::Clamp_To_Edge: - return aiTextureMapMode_Clamp; + case SamplerWrap::Clamp_To_Edge: + return aiTextureMapMode_Clamp; - case SamplerWrap::UNSET: - case SamplerWrap::Repeat: - default: - return aiTextureMapMode_Wrap; + case SamplerWrap::UNSET: + case SamplerWrap::Repeat: + default: + return aiTextureMapMode_Wrap; } } @@ -185,8 +185,9 @@ static void SetMaterialTextureProperty(std::vector &embeddedTexIdxs, Asset // coordinate of the actual meshes during import. const ai_real rcos(cos(-transform.mRotation)); const ai_real rsin(sin(-transform.mRotation)); - transform.mTranslation.x = (static_cast( 0.5 ) * transform.mScaling.x) * (-rcos + rsin + 1) + prop.TextureTransformExt_t.offset[0]; - transform.mTranslation.y = ((static_cast( 0.5 ) * transform.mScaling.y) * (rsin + rcos - 1)) + 1 - transform.mScaling.y - prop.TextureTransformExt_t.offset[1];; + transform.mTranslation.x = (static_cast(0.5) * transform.mScaling.x) * (-rcos + rsin + 1) + prop.TextureTransformExt_t.offset[0]; + transform.mTranslation.y = ((static_cast(0.5) * transform.mScaling.y) * (rsin + rcos - 1)) + 1 - transform.mScaling.y - prop.TextureTransformExt_t.offset[1]; + ; mat->AddProperty(&transform, 1, _AI_MATKEY_UVTRANSFORM_BASE, texType, texSlot); } @@ -305,7 +306,6 @@ static aiMaterial *ImportMaterial(std::vector &embeddedTexIdxs, Asset &r, M aimat->AddProperty(&shadingMode, 1, AI_MATKEY_SHADING_MODEL); - // KHR_materials_sheen if (mat.materialSheen.isPresent) { MaterialSheen &sheen = mat.materialSheen.value; @@ -378,7 +378,7 @@ void glTF2Importer::ImportMaterials(Asset &r) { } } -static inline void SetFaceAndAdvance1(aiFace*& face, unsigned int numVertices, unsigned int a) { +static inline void SetFaceAndAdvance1(aiFace *&face, unsigned int numVertices, unsigned int a) { if (a >= numVertices) { return; } @@ -388,7 +388,7 @@ static inline void SetFaceAndAdvance1(aiFace*& face, unsigned int numVertices, u ++face; } -static inline void SetFaceAndAdvance2(aiFace*& face, unsigned int numVertices, +static inline void SetFaceAndAdvance2(aiFace *&face, unsigned int numVertices, unsigned int a, unsigned int b) { if ((a >= numVertices) || (b >= numVertices)) { return; @@ -400,7 +400,7 @@ static inline void SetFaceAndAdvance2(aiFace*& face, unsigned int numVertices, ++face; } -static inline void SetFaceAndAdvance3(aiFace*& face, unsigned int numVertices, unsigned int a, +static inline void SetFaceAndAdvance3(aiFace *&face, unsigned int numVertices, unsigned int a, unsigned int b, unsigned int c) { if ((a >= numVertices) || (b >= numVertices) || (c >= numVertices)) { return; @@ -427,17 +427,16 @@ static inline bool CheckValidFacesIndices(aiFace *faces, unsigned nFaces, unsign } #endif // ASSIMP_BUILD_DEBUG -template -aiColor4D* GetVertexColorsForType(Ref input) { +template +aiColor4D *GetVertexColorsForType(Ref input) { constexpr float max = std::numeric_limits::max(); - aiColor4t* colors; + aiColor4t *colors; input->ExtractData(colors); auto output = new aiColor4D[input->count]; for (size_t i = 0; i < input->count; i++) { output[i] = aiColor4D( - colors[i].r / max, colors[i].g / max, - colors[i].b / max, colors[i].a / max - ); + colors[i].r / max, colors[i].g / max, + colors[i].b / max, colors[i].a / max); } delete[] colors; return output; @@ -471,21 +470,21 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { } switch (prim.mode) { - case PrimitiveMode_POINTS: - aim->mPrimitiveTypes |= aiPrimitiveType_POINT; - break; + case PrimitiveMode_POINTS: + aim->mPrimitiveTypes |= aiPrimitiveType_POINT; + break; - case PrimitiveMode_LINES: - case PrimitiveMode_LINE_LOOP: - case PrimitiveMode_LINE_STRIP: - aim->mPrimitiveTypes |= aiPrimitiveType_LINE; - break; + case PrimitiveMode_LINES: + case PrimitiveMode_LINE_LOOP: + case PrimitiveMode_LINE_STRIP: + aim->mPrimitiveTypes |= aiPrimitiveType_LINE; + break; - case PrimitiveMode_TRIANGLES: - case PrimitiveMode_TRIANGLE_STRIP: - case PrimitiveMode_TRIANGLE_FAN: - aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; - break; + case PrimitiveMode_TRIANGLES: + case PrimitiveMode_TRIANGLE_STRIP: + case PrimitiveMode_TRIANGLE_FAN: + aim->mPrimitiveTypes |= aiPrimitiveType_TRIANGLE; + break; } Mesh::Primitive::Attributes &attr = prim.attributes; @@ -528,7 +527,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { for (size_t c = 0; c < attr.color.size() && c < AI_MAX_NUMBER_OF_COLOR_SETS; ++c) { if (attr.color[c]->count != aim->mNumVertices) { DefaultLogger::get()->warn("Color stream size in mesh \"", mesh.name, - "\" does not match the vertex count"); + "\" does not match the vertex count"); continue; } @@ -551,7 +550,7 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { if (attr.texcoord[tc]->count != aim->mNumVertices) { DefaultLogger::get()->warn("Texcoord stream size in mesh \"", mesh.name, - "\" does not match the vertex count"); + "\" does not match the vertex count"); continue; } @@ -644,77 +643,77 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { } switch (prim.mode) { - case PrimitiveMode_POINTS: { - nFaces = count; - facePtr = faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < count; ++i) { - SetFaceAndAdvance1(facePtr, aim->mNumVertices, data.GetUInt(i)); - } - break; + case PrimitiveMode_POINTS: { + nFaces = count; + facePtr = faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; ++i) { + SetFaceAndAdvance1(facePtr, aim->mNumVertices, data.GetUInt(i)); } + break; + } - case PrimitiveMode_LINES: { - nFaces = count / 2; - if (nFaces * 2 != count) { - ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped."); - count = nFaces * 2; - } - facePtr = faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < count; i += 2) { - SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1)); - } - break; + case PrimitiveMode_LINES: { + nFaces = count / 2; + if (nFaces * 2 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped."); + count = nFaces * 2; } - - case PrimitiveMode_LINE_LOOP: - case PrimitiveMode_LINE_STRIP: { - nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); - facePtr = faces = new aiFace[nFaces]; - SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1)); - for (unsigned int i = 2; i < count; ++i) { - SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(i - 1), data.GetUInt(i)); - } - if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop - SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(static_cast(count) - 1), faces[0].mIndices[0]); - } - break; + facePtr = faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; i += 2) { + SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1)); } + break; + } - case PrimitiveMode_TRIANGLES: { - nFaces = count / 3; - if (nFaces * 3 != count) { - ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped."); - count = nFaces * 3; - } - facePtr = faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < count; i += 3) { + case PrimitiveMode_LINE_LOOP: + case PrimitiveMode_LINE_STRIP: { + nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); + facePtr = faces = new aiFace[nFaces]; + SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1)); + for (unsigned int i = 2; i < count; ++i) { + SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(i - 1), data.GetUInt(i)); + } + if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop + SetFaceAndAdvance2(facePtr, aim->mNumVertices, data.GetUInt(static_cast(count) - 1), faces[0].mIndices[0]); + } + break; + } + + case PrimitiveMode_TRIANGLES: { + nFaces = count / 3; + if (nFaces * 3 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped."); + count = nFaces * 3; + } + facePtr = faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; i += 3) { + SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); + } + break; + } + case PrimitiveMode_TRIANGLE_STRIP: { + nFaces = count - 2; + facePtr = faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < nFaces; ++i) { + //The ordering is to ensure that the triangles are all drawn with the same orientation + if ((i + 1) % 2 == 0) { + //For even n, vertices n + 1, n, and n + 2 define triangle n + SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i + 1), data.GetUInt(i), data.GetUInt(i + 2)); + } else { + //For odd n, vertices n, n+1, and n+2 define triangle n SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); } - break; } - case PrimitiveMode_TRIANGLE_STRIP: { - nFaces = count - 2; - facePtr = faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < nFaces; ++i) { - //The ordering is to ensure that the triangles are all drawn with the same orientation - if ((i + 1) % 2 == 0) { - //For even n, vertices n + 1, n, and n + 2 define triangle n - SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i + 1), data.GetUInt(i), data.GetUInt(i + 2)); - } else { - //For odd n, vertices n, n+1, and n+2 define triangle n - SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(i), data.GetUInt(i + 1), data.GetUInt(i + 2)); - } - } - break; + break; + } + case PrimitiveMode_TRIANGLE_FAN: + nFaces = count - 2; + facePtr = faces = new aiFace[nFaces]; + SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); + for (unsigned int i = 1; i < nFaces; ++i) { + SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(i + 1), data.GetUInt(i + 2)); } - case PrimitiveMode_TRIANGLE_FAN: - nFaces = count - 2; - facePtr = faces = new aiFace[nFaces]; - SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(1), data.GetUInt(2)); - for (unsigned int i = 1; i < nFaces; ++i) { - SetFaceAndAdvance3(facePtr, aim->mNumVertices, data.GetUInt(0), data.GetUInt(i + 1), data.GetUInt(i + 2)); - } - break; + break; } } else { // no indices provided so directly generate from counts @@ -722,77 +721,77 @@ void glTF2Importer::ImportMeshes(glTF2::Asset &r) { unsigned int count = aim->mNumVertices; switch (prim.mode) { - case PrimitiveMode_POINTS: { - nFaces = count; - facePtr = faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < count; ++i) { - SetFaceAndAdvance1(facePtr, aim->mNumVertices, i); - } - break; + case PrimitiveMode_POINTS: { + nFaces = count; + facePtr = faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; ++i) { + SetFaceAndAdvance1(facePtr, aim->mNumVertices, i); } + break; + } - case PrimitiveMode_LINES: { - nFaces = count / 2; - if (nFaces * 2 != count) { - ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped."); - count = (unsigned int)nFaces * 2; - } - facePtr = faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < count; i += 2) { - SetFaceAndAdvance2(facePtr, aim->mNumVertices, i, i + 1); - } - break; + case PrimitiveMode_LINES: { + nFaces = count / 2; + if (nFaces * 2 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the LINES mode. Some vertices were dropped."); + count = (unsigned int)nFaces * 2; } - - case PrimitiveMode_LINE_LOOP: - case PrimitiveMode_LINE_STRIP: { - nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); - facePtr = faces = new aiFace[nFaces]; - SetFaceAndAdvance2(facePtr, aim->mNumVertices, 0, 1); - for (unsigned int i = 2; i < count; ++i) { - SetFaceAndAdvance2(facePtr, aim->mNumVertices, i - 1, i); - } - if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop - SetFaceAndAdvance2(facePtr, aim->mNumVertices, count - 1, 0); - } - break; + facePtr = faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; i += 2) { + SetFaceAndAdvance2(facePtr, aim->mNumVertices, i, i + 1); } + break; + } - case PrimitiveMode_TRIANGLES: { - nFaces = count / 3; - if (nFaces * 3 != count) { - ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped."); - count = (unsigned int)nFaces * 3; - } - facePtr = faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < count; i += 3) { + case PrimitiveMode_LINE_LOOP: + case PrimitiveMode_LINE_STRIP: { + nFaces = count - ((prim.mode == PrimitiveMode_LINE_STRIP) ? 1 : 0); + facePtr = faces = new aiFace[nFaces]; + SetFaceAndAdvance2(facePtr, aim->mNumVertices, 0, 1); + for (unsigned int i = 2; i < count; ++i) { + SetFaceAndAdvance2(facePtr, aim->mNumVertices, i - 1, i); + } + if (prim.mode == PrimitiveMode_LINE_LOOP) { // close the loop + SetFaceAndAdvance2(facePtr, aim->mNumVertices, count - 1, 0); + } + break; + } + + case PrimitiveMode_TRIANGLES: { + nFaces = count / 3; + if (nFaces * 3 != count) { + ASSIMP_LOG_WARN("The number of vertices was not compatible with the TRIANGLES mode. Some vertices were dropped."); + count = (unsigned int)nFaces * 3; + } + facePtr = faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < count; i += 3) { + SetFaceAndAdvance3(facePtr, aim->mNumVertices, i, i + 1, i + 2); + } + break; + } + case PrimitiveMode_TRIANGLE_STRIP: { + nFaces = count - 2; + facePtr = faces = new aiFace[nFaces]; + for (unsigned int i = 0; i < nFaces; ++i) { + //The ordering is to ensure that the triangles are all drawn with the same orientation + if ((i + 1) % 2 == 0) { + //For even n, vertices n + 1, n, and n + 2 define triangle n + SetFaceAndAdvance3(facePtr, aim->mNumVertices, i + 1, i, i + 2); + } else { + //For odd n, vertices n, n+1, and n+2 define triangle n SetFaceAndAdvance3(facePtr, aim->mNumVertices, i, i + 1, i + 2); } - break; } - case PrimitiveMode_TRIANGLE_STRIP: { - nFaces = count - 2; - facePtr = faces = new aiFace[nFaces]; - for (unsigned int i = 0; i < nFaces; ++i) { - //The ordering is to ensure that the triangles are all drawn with the same orientation - if ((i + 1) % 2 == 0) { - //For even n, vertices n + 1, n, and n + 2 define triangle n - SetFaceAndAdvance3(facePtr, aim->mNumVertices, i + 1, i, i + 2); - } else { - //For odd n, vertices n, n+1, and n+2 define triangle n - SetFaceAndAdvance3(facePtr, aim->mNumVertices, i, i + 1, i + 2); - } - } - break; + break; + } + case PrimitiveMode_TRIANGLE_FAN: + nFaces = count - 2; + facePtr = faces = new aiFace[nFaces]; + SetFaceAndAdvance3(facePtr, aim->mNumVertices, 0, 1, 2); + for (unsigned int i = 1; i < nFaces; ++i) { + SetFaceAndAdvance3(facePtr, aim->mNumVertices, 0, i + 1, i + 2); } - case PrimitiveMode_TRIANGLE_FAN: - nFaces = count - 2; - facePtr = faces = new aiFace[nFaces]; - SetFaceAndAdvance3(facePtr, aim->mNumVertices, 0, 1, 2); - for (unsigned int i = 1; i < nFaces; ++i) { - SetFaceAndAdvance3(facePtr, aim->mNumVertices, 0, i + 1, i + 2); - } - break; + break; } } @@ -876,15 +875,15 @@ void glTF2Importer::ImportLights(glTF2::Asset &r) { aiLight *ail = mScene->mLights[i] = new aiLight(); switch (light.type) { - case Light::Directional: - ail->mType = aiLightSource_DIRECTIONAL; - break; - case Light::Point: - ail->mType = aiLightSource_POINT; - break; - case Light::Spot: - ail->mType = aiLightSource_SPOT; - break; + case Light::Directional: + ail->mType = aiLightSource_DIRECTIONAL; + break; + case Light::Point: + ail->mType = aiLightSource_POINT; + break; + case Light::Spot: + ail->mType = aiLightSource_SPOT; + break; } if (ail->mType != aiLightSource_POINT) { @@ -926,7 +925,7 @@ static void GetNodeTransform(aiMatrix4x4 &matrix, const glTF2::Node &node) { if (node.matrix.isPresent) { CopyValue(node.matrix.value, matrix); return; - } + } if (node.translation.isPresent) { aiVector3D trans; @@ -1021,7 +1020,7 @@ void ParseExtensions(aiMetadata *metadata, const CustomExtension &extension) { metadata->Add(extension.name, extension.mBoolValue.value); } else if (extension.mValues.isPresent) { aiMetadata val; - for (auto const & subExtension : extension.mValues.value) { + for (auto const &subExtension : extension.mValues.value) { ParseExtensions(&val, subExtension); } metadata->Add(extension.name, val); @@ -1030,7 +1029,7 @@ void ParseExtensions(aiMetadata *metadata, const CustomExtension &extension) { void ParseExtras(aiMetadata *metadata, const CustomExtension &extension) { if (extension.mValues.isPresent) { - for (auto const & subExtension : extension.mValues.value) { + for (auto const &subExtension : extension.mValues.value) { ParseExtensions(metadata, subExtension); } } @@ -1068,11 +1067,10 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector & if (!node.meshes.empty()) { // GLTF files contain at most 1 mesh per node. - if (node.meshes.size() > 1) - { + if (node.meshes.size() > 1) { throw DeadlyImportError("GLTF: Invalid input, found ", node.meshes.size(), - " meshes in ", getContextForErrorMessages(node.id, node.name), - ", but only 1 mesh per node allowed."); + " meshes in ", getContextForErrorMessages(node.id, node.name), + ", but only 1 mesh per node allowed."); } int mesh_idx = node.meshes[0].GetIndex(); int count = meshOffsets[mesh_idx + 1] - meshOffsets[mesh_idx]; @@ -1083,7 +1081,7 @@ aiNode *ImportNode(aiScene *pScene, glTF2::Asset &r, std::vector & if (node.skin) { for (int primitiveNo = 0; primitiveNo < count; ++primitiveNo) { aiMesh *mesh = pScene->mMeshes[meshOffsets[mesh_idx] + primitiveNo]; - unsigned int numBones =static_cast(node.skin->jointNames.size()); + unsigned int numBones = static_cast(node.skin->jointNames.size()); std::vector> weighting(numBones); BuildVertexWeightMapping(node.meshes[0]->primitives[primitiveNo], weighting); @@ -1222,7 +1220,7 @@ struct AnimationSamplers { Animation::Sampler *weight; }; -aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &samplers) { +aiNodeAnim *CreateNodeAnim(glTF2::Asset &, Node &node, AnimationSamplers &samplers) { aiNodeAnim *anim = new aiNodeAnim(); try { @@ -1313,7 +1311,7 @@ aiNodeAnim *CreateNodeAnim(glTF2::Asset&, Node &node, AnimationSamplers &sampler } } -aiMeshMorphAnim *CreateMeshMorphAnim(glTF2::Asset&, Node &node, AnimationSamplers &samplers) { +aiMeshMorphAnim *CreateMeshMorphAnim(glTF2::Asset &, Node &node, AnimationSamplers &samplers) { auto *anim = new aiMeshMorphAnim(); try { @@ -1366,7 +1364,7 @@ std::unordered_map GatherSamplers(Animation &an continue; } - auto& animsampler = anim.samplers[channel.sampler]; + auto &animsampler = anim.samplers[channel.sampler]; if (!animsampler.input) { ASSIMP_LOG_WARN("Animation ", anim.name, ": Missing sampler input. Skipping."); @@ -1555,9 +1553,9 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) { if (ext) { if (strcmp(ext, "jpeg") == 0) { ext = "jpg"; - } else if(strcmp(ext, "ktx2") == 0) { //basisu: ktx remains + } else if (strcmp(ext, "ktx2") == 0) { //basisu: ktx remains ext = "kx2"; - } else if(strcmp(ext, "basis") == 0) { //basisu + } else if (strcmp(ext, "basis") == 0) { //basisu ext = "bu"; } @@ -1570,7 +1568,7 @@ void glTF2Importer::ImportEmbeddedTextures(glTF2::Asset &r) { } } -void glTF2Importer::ImportCommonMetadata(glTF2::Asset& a) { +void glTF2Importer::ImportCommonMetadata(glTF2::Asset &a) { ASSIMP_LOG_DEBUG("Importing metadata"); ai_assert(mScene->mMetaData == nullptr); const bool hasVersion = !a.asset.version.empty(); @@ -1604,7 +1602,7 @@ void glTF2Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IO this->mScene = pScene; // read the asset file - glTF2::Asset asset(pIOHandler, static_cast(mSchemaDocumentProvider)); + glTF2::Asset asset(pIOHandler, static_cast(mSchemaDocumentProvider)); asset.Load(pFile, GetExtension(pFile) == "glb"); if (asset.scene) { pScene->mName = asset.scene->name; @@ -1631,7 +1629,7 @@ void glTF2Importer::InternReadFile(const std::string &pFile, aiScene *pScene, IO } void glTF2Importer::SetupProperties(const Importer *pImp) { - mSchemaDocumentProvider = static_cast(pImp->GetPropertyPointer(AI_CONFIG_IMPORT_SCHEMA_DOCUMENT_PROVIDER)); + mSchemaDocumentProvider = static_cast(pImp->GetPropertyPointer(AI_CONFIG_IMPORT_SCHEMA_DOCUMENT_PROVIDER)); } #endif // ASSIMP_BUILD_NO_GLTF_IMPORTER From cfe84b92603ae33984802b1bc15e8a7f4a487682 Mon Sep 17 00:00:00 2001 From: Sergio Acereda Date: Thu, 3 Mar 2022 16:18:25 +0100 Subject: [PATCH 11/16] Use generic METALNESS and DIFFUSE_ROUGHNESS texture types --- code/AssetLib/glTF2/glTF2Importer.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/code/AssetLib/glTF2/glTF2Importer.cpp b/code/AssetLib/glTF2/glTF2Importer.cpp index a95e752d7..e8b8562e6 100644 --- a/code/AssetLib/glTF2/glTF2Importer.cpp +++ b/code/AssetLib/glTF2/glTF2Importer.cpp @@ -260,7 +260,10 @@ static aiMaterial *ImportMaterial(std::vector &embeddedTexIdxs, Asset &r, M SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_DIFFUSE); SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.baseColorTexture, aimat, aiTextureType_BASE_COLOR); + // Keep AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE for backwards compatibility SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, AI_MATKEY_GLTF_PBRMETALLICROUGHNESS_METALLICROUGHNESS_TEXTURE); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, aiTextureType_METALNESS); + SetMaterialTextureProperty(embeddedTexIdxs, r, mat.pbrMetallicRoughness.metallicRoughnessTexture, aimat, aiTextureType_DIFFUSE_ROUGHNESS); aimat->AddProperty(&mat.pbrMetallicRoughness.metallicFactor, 1, AI_MATKEY_METALLIC_FACTOR); aimat->AddProperty(&mat.pbrMetallicRoughness.roughnessFactor, 1, AI_MATKEY_ROUGHNESS_FACTOR); From 80a8807c4732696c02407ee7443e07792fd2bdc2 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Sat, 5 Mar 2022 20:37:34 +0100 Subject: [PATCH 12/16] Fix compiler warnings --- code/AssetLib/LWO/LWOLoader.cpp | 2 +- code/AssetLib/LWO/LWOMaterial.cpp | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/code/AssetLib/LWO/LWOLoader.cpp b/code/AssetLib/LWO/LWOLoader.cpp index 0453cc9c8..c4e85bc50 100644 --- a/code/AssetLib/LWO/LWOLoader.cpp +++ b/code/AssetLib/LWO/LWOLoader.cpp @@ -82,8 +82,8 @@ static const aiImporterDesc desc = { // Constructor to be privately used by Importer LWOImporter::LWOImporter() : mIsLWO2(), - mIsLWO3(), mIsLXOB(), + mIsLWO3(), mLayers(), mCurLayer(), mTags(), diff --git a/code/AssetLib/LWO/LWOMaterial.cpp b/code/AssetLib/LWO/LWOMaterial.cpp index 5e5a11348..4728706db 100644 --- a/code/AssetLib/LWO/LWOMaterial.cpp +++ b/code/AssetLib/LWO/LWOMaterial.cpp @@ -885,17 +885,13 @@ void LWOImporter::LoadNodeData(unsigned int size) { GetS0(valueType, 8); if (valueType == "int") { - uint32_t value; - value = GetU4(); + static_cast(GetU4()); } else if (valueType == "double") { - uint64_t value; - value = GetU8(); + static_cast(GetU8()); } else if (valueType == "vparam") { mFileBuffer += 24; - float value; - value = GetF8(); - + float value = GetF8(); if (attrName == "Diffuse") { surf.mDiffuseValue = value; } else if (attrName == "Specular") { From 76e10b96fc67b919e17d984b460ea780e122ffdd Mon Sep 17 00:00:00 2001 From: kimkulling Date: Wed, 9 Mar 2022 10:51:37 +0100 Subject: [PATCH 13/16] Fix missing members and do some small refactorings. --- code/AssetLib/FBX/FBXDocument.cpp | 125 ++++++++---------------------- code/AssetLib/FBX/FBXDocument.h | 52 ++++++------- code/AssetLib/FBX/FBXMaterial.cpp | 23 +++++- code/AssetLib/FBX/FBXModel.cpp | 5 -- 4 files changed, 76 insertions(+), 129 deletions(-) diff --git a/code/AssetLib/FBX/FBXDocument.cpp b/code/AssetLib/FBX/FBXDocument.cpp index f228b1749..b49ee625a 100644 --- a/code/AssetLib/FBX/FBXDocument.cpp +++ b/code/AssetLib/FBX/FBXDocument.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -68,23 +67,13 @@ namespace FBX { using namespace Util; // ------------------------------------------------------------------------------------------------ -LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc) -: doc(doc) -, element(element) -, id(id) -, flags() { +LazyObject::LazyObject(uint64_t id, const Element& element, const Document& doc) : + doc(doc), element(element), id(id), flags() { // empty } // ------------------------------------------------------------------------------------------------ -LazyObject::~LazyObject() -{ - // empty -} - -// ------------------------------------------------------------------------------------------------ -const Object* LazyObject::Get(bool dieOnError) -{ +const Object* LazyObject::Get(bool dieOnError) { if(IsBeingConstructed() || FailedToConstruct()) { return nullptr; } @@ -234,17 +223,8 @@ const Object* LazyObject::Get(bool dieOnError) } // ------------------------------------------------------------------------------------------------ -Object::Object(uint64_t id, const Element& element, const std::string& name) -: element(element) -, name(name) -, id(id) -{ - // empty -} - -// ------------------------------------------------------------------------------------------------ -Object::~Object() -{ +Object::Object(uint64_t id, const Element& element, const std::string& name) : + element(element), name(name), id(id) { // empty } @@ -255,16 +235,8 @@ FileGlobalSettings::FileGlobalSettings(const Document &doc, std::shared_ptrCompound() ) { @@ -370,8 +340,7 @@ void Document::ReadGlobalSettings() } // ------------------------------------------------------------------------------------------------ -void Document::ReadObjects() -{ +void Document::ReadObjects() { // read ID objects from "Objects" section const Scope& sc = parser.GetRootScope(); const Element* const eobjects = sc["Objects"]; @@ -418,8 +387,7 @@ void Document::ReadObjects() } // ------------------------------------------------------------------------------------------------ -void Document::ReadPropertyTemplates() -{ +void Document::ReadPropertyTemplates() { const Scope& sc = parser.GetRootScope(); // read property templates from "Definitions" section const Element* const edefs = sc["Definitions"]; @@ -476,8 +444,7 @@ void Document::ReadPropertyTemplates() } // ------------------------------------------------------------------------------------------------ -void Document::ReadConnections() -{ +void Document::ReadConnections() { const Scope& sc = parser.GetRootScope(); // read property templates from "Definitions" section const Element* const econns = sc["Connections"]; @@ -524,8 +491,7 @@ void Document::ReadConnections() } // ------------------------------------------------------------------------------------------------ -const std::vector& Document::AnimationStacks() const -{ +const std::vector& Document::AnimationStacks() const { if (!animationStacksResolved.empty() || animationStacks.empty()) { return animationStacksResolved; } @@ -545,17 +511,15 @@ const std::vector& Document::AnimationStacks() const } // ------------------------------------------------------------------------------------------------ -LazyObject* Document::GetObject(uint64_t id) const -{ +LazyObject* Document::GetObject(uint64_t id) const { ObjectMap::const_iterator it = objects.find(id); return it == objects.end() ? nullptr : (*it).second; } -#define MAX_CLASSNAMES 6 +constexpr size_t MAX_CLASSNAMES = 6; // ------------------------------------------------------------------------------------------------ -std::vector Document::GetConnectionsSequenced(uint64_t id, const ConnectionMap& conns) const -{ +std::vector Document::GetConnectionsSequenced(uint64_t id, const ConnectionMap& conns) const { std::vector temp; const std::pair range = @@ -573,11 +537,9 @@ std::vector Document::GetConnectionsSequenced(uint64_t id, co // ------------------------------------------------------------------------------------------------ std::vector Document::GetConnectionsSequenced(uint64_t id, bool is_src, - const ConnectionMap& conns, - const char* const* classnames, - size_t count) const - -{ + const ConnectionMap& conns, + const char* const* classnames, + size_t count) const { ai_assert(classnames); ai_assert( count != 0 ); ai_assert( count <= MAX_CLASSNAMES); @@ -622,95 +584,72 @@ std::vector Document::GetConnectionsSequenced(uint64_t id, bo } // ------------------------------------------------------------------------------------------------ -std::vector Document::GetConnectionsBySourceSequenced(uint64_t source) const -{ +std::vector Document::GetConnectionsBySourceSequenced(uint64_t source) const { return GetConnectionsSequenced(source, ConnectionsBySource()); } // ------------------------------------------------------------------------------------------------ -std::vector Document::GetConnectionsBySourceSequenced(uint64_t src, const char* classname) const -{ +std::vector Document::GetConnectionsBySourceSequenced(uint64_t src, const char* classname) const { const char* arr[] = {classname}; return GetConnectionsBySourceSequenced(src, arr,1); } // ------------------------------------------------------------------------------------------------ std::vector Document::GetConnectionsBySourceSequenced(uint64_t source, - const char* const* classnames, size_t count) const -{ + const char* const* classnames, size_t count) const { return GetConnectionsSequenced(source, true, ConnectionsBySource(),classnames, count); } // ------------------------------------------------------------------------------------------------ std::vector Document::GetConnectionsByDestinationSequenced(uint64_t dest, - const char* classname) const -{ + const char* classname) const { const char* arr[] = {classname}; return GetConnectionsByDestinationSequenced(dest, arr,1); } // ------------------------------------------------------------------------------------------------ -std::vector Document::GetConnectionsByDestinationSequenced(uint64_t dest) const -{ +std::vector Document::GetConnectionsByDestinationSequenced(uint64_t dest) const { return GetConnectionsSequenced(dest, ConnectionsByDestination()); } // ------------------------------------------------------------------------------------------------ std::vector Document::GetConnectionsByDestinationSequenced(uint64_t dest, - const char* const* classnames, size_t count) const - -{ + const char* const* classnames, size_t count) const { return GetConnectionsSequenced(dest, false, ConnectionsByDestination(),classnames, count); } // ------------------------------------------------------------------------------------------------ Connection::Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop, - const Document& doc) - -: insertionOrder(insertionOrder) -, prop(prop) -, src(src) -, dest(dest) -, doc(doc) -{ + const Document& doc) : + insertionOrder(insertionOrder), prop(prop), src(src), dest(dest), doc(doc) { ai_assert(doc.Objects().find(src) != doc.Objects().end()); // dest may be 0 (root node) ai_assert(!dest || doc.Objects().find(dest) != doc.Objects().end()); } // ------------------------------------------------------------------------------------------------ -Connection::~Connection() -{ - // empty -} - -// ------------------------------------------------------------------------------------------------ -LazyObject& Connection::LazySourceObject() const -{ +LazyObject& Connection::LazySourceObject() const { LazyObject* const lazy = doc.GetObject(src); ai_assert(lazy); return *lazy; } // ------------------------------------------------------------------------------------------------ -LazyObject& Connection::LazyDestinationObject() const -{ +LazyObject& Connection::LazyDestinationObject() const { LazyObject* const lazy = doc.GetObject(dest); ai_assert(lazy); return *lazy; } // ------------------------------------------------------------------------------------------------ -const Object* Connection::SourceObject() const -{ +const Object* Connection::SourceObject() const { LazyObject* const lazy = doc.GetObject(src); ai_assert(lazy); return lazy->Get(); } // ------------------------------------------------------------------------------------------------ -const Object* Connection::DestinationObject() const -{ +const Object* Connection::DestinationObject() const { LazyObject* const lazy = doc.GetObject(dest); ai_assert(lazy); return lazy->Get(); @@ -719,4 +658,4 @@ const Object* Connection::DestinationObject() const } // !FBX } // !Assimp -#endif +#endif // ASSIMP_BUILD_NO_FBX_IMPORTER diff --git a/code/AssetLib/FBX/FBXDocument.h b/code/AssetLib/FBX/FBXDocument.h index bac7e7769..04da83c06 100644 --- a/code/AssetLib/FBX/FBXDocument.h +++ b/code/AssetLib/FBX/FBXDocument.h @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -89,7 +88,7 @@ class LazyObject { public: LazyObject(uint64_t id, const Element& element, const Document& doc); - ~LazyObject(); + ~LazyObject() = default; const Object* Get(bool dieOnError = false); @@ -139,7 +138,7 @@ class Object { public: Object(uint64_t id, const Element& element, const std::string& name); - virtual ~Object(); + virtual ~Object() = default; const Element& SourceElement() const { return element; @@ -267,8 +266,7 @@ public: Light(uint64_t id, const Element& element, const Document& doc, const std::string& name); virtual ~Light(); - enum Type - { + enum Type { Type_Point, Type_Directional, Type_Spot, @@ -278,8 +276,7 @@ public: Type_MAX // end-of-enum sentinel }; - enum Decay - { + enum Decay { Decay_None, Decay_Linear, Decay_Quadratic, @@ -578,31 +575,27 @@ public: BlendMode_BlendModeCount }; - const Texture* getTexture(int index=0) const - { + const Texture* getTexture(int index=0) const { return textures[index]; - } int textureCount() const { return static_cast(textures.size()); } - BlendMode GetBlendMode() const - { + BlendMode GetBlendMode() const { return blendMode; } - float Alpha() - { + float Alpha() { return alpha; } + private: std::vector textures; BlendMode blendMode; float alpha; }; -typedef std::fbx_unordered_map TextureMap; -typedef std::fbx_unordered_map LayeredTextureMap; - +using TextureMap = std::fbx_unordered_map; +using LayeredTextureMap = std::fbx_unordered_map; /** DOM class for generic FBX videos */ class Video : public Object { @@ -690,8 +683,8 @@ private: LayeredTextureMap layeredTextures; }; -typedef std::vector KeyTimeList; -typedef std::vector KeyValueList; +using KeyTimeList = std::vector; +using KeyValueList = std::vector; /** Represents a FBX animation curve (i.e. a 1-dimensional set of keyframes and values therefore) */ class AnimationCurve : public Object { @@ -727,7 +720,7 @@ private: }; // property-name -> animation curve -typedef std::map AnimationCurveMap; +using AnimationCurveMap = std::map; /** Represents a FBX animation curve (i.e. a mapping from single animation curves to nodes) */ class AnimationCurveNode : public Object { @@ -777,7 +770,7 @@ private: const Document& doc; }; -typedef std::vector AnimationCurveNodeList; +using AnimationCurveNodeList = std::vector; /** Represents a FBX animation layer (i.e. a list of node animations) */ class AnimationLayer : public Object { @@ -800,7 +793,7 @@ private: const Document& doc; }; -typedef std::vector AnimationLayerList; +using AnimationLayerList = std::vector; /** Represents a FBX animation stack (i.e. a list of animation layers) */ class AnimationStack : public Object { @@ -843,8 +836,8 @@ private: std::shared_ptr props; }; -typedef std::vector WeightArray; -typedef std::vector WeightIndexArray; +using WeightArray = std::vector; +using WeightIndexArray = std::vector; /** DOM class for BlendShapeChannel deformers */ @@ -956,7 +949,7 @@ class Connection { public: Connection(uint64_t insertionOrder, uint64_t src, uint64_t dest, const std::string& prop, const Document& doc); - ~Connection(); + ~Connection() = default; // note: a connection ensures that the source and dest objects exist, but // not that they have DOM representations, so the return value of one of @@ -1011,10 +1004,9 @@ public: // during their entire lifetime (Document). FBX files have // up to many thousands of objects (most of which we never use), // so the memory overhead for them should be kept at a minimum. -typedef std::fbx_unordered_map ObjectMap; -typedef std::fbx_unordered_map > PropertyTemplateMap; - -typedef std::fbx_unordered_multimap ConnectionMap; +using ObjectMap = std::fbx_unordered_map ; +using PropertyTemplateMap = std::fbx_unordered_map > ; +using ConnectionMap = std::fbx_unordered_multimap; /** DOM class for global document settings, a single instance per document can * be accessed via Document.Globals(). */ @@ -1022,7 +1014,7 @@ class FileGlobalSettings { public: FileGlobalSettings(const Document& doc, std::shared_ptr props); - ~FileGlobalSettings(); + ~FileGlobalSettings() = default; const PropertyTable& Props() const { ai_assert(props.get()); diff --git a/code/AssetLib/FBX/FBXMaterial.cpp b/code/AssetLib/FBX/FBXMaterial.cpp index 8849179f3..2162670f8 100644 --- a/code/AssetLib/FBX/FBXMaterial.cpp +++ b/code/AssetLib/FBX/FBXMaterial.cpp @@ -140,11 +140,32 @@ Material::~Material() { // empty } + aiVector2D uvTrans; + aiVector2D uvScaling; + ai_real uvRotation; + + std::string type; + std::string relativeFileName; + std::string fileName; + std::string alphaSource; + std::shared_ptr props; + + unsigned int crop[4]{}; + + const Video* media; + // ------------------------------------------------------------------------------------------------ Texture::Texture(uint64_t id, const Element& element, const Document& doc, const std::string& name) : Object(id,element,name), + uvTrans(0.0f, 0.0f), uvScaling(1.0f,1.0f), - media(0) { + uvRotation(0.0f), + type(), + relativeFileName(), + fileName(), + alphaSource(), + props(), + media(nullptr) { const Scope& sc = GetRequiredScope(element); const Element* const Type = sc["Type"]; diff --git a/code/AssetLib/FBX/FBXModel.cpp b/code/AssetLib/FBX/FBXModel.cpp index 9fe4cd5f8..d731d2e29 100644 --- a/code/AssetLib/FBX/FBXModel.cpp +++ b/code/AssetLib/FBX/FBXModel.cpp @@ -4,7 +4,6 @@ Open Asset Import Library (assimp) Copyright (c) 2006-2022, assimp team - All rights reserved. Redistribution and use of this software in source and binary forms, @@ -76,10 +75,6 @@ Model::Model(uint64_t id, const Element &element, const Document &doc, const std ResolveLinks(element, doc); } -// ------------------------------------------------------------------------------------------------ -Model::~Model() { -} - // ------------------------------------------------------------------------------------------------ void Model::ResolveLinks(const Element&, const Document &doc) { const char *const arr[] = { "Geometry", "Material", "NodeAttribute" }; From 26598dc6bdf11ebf1328c0907461b8da1dde8571 Mon Sep 17 00:00:00 2001 From: kimkulling Date: Wed, 9 Mar 2022 11:00:05 +0100 Subject: [PATCH 14/16] Forget to save file. --- code/AssetLib/FBX/FBXDocument.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/AssetLib/FBX/FBXDocument.h b/code/AssetLib/FBX/FBXDocument.h index 04da83c06..c61a47410 100644 --- a/code/AssetLib/FBX/FBXDocument.h +++ b/code/AssetLib/FBX/FBXDocument.h @@ -344,7 +344,7 @@ public: Model(uint64_t id, const Element& element, const Document& doc, const std::string& name); - virtual ~Model(); + virtual ~Model() = default; fbx_simple_property(QuaternionInterpolate, int, 0) From c14eccefaf0ba0286d2e9f3ae7b8dd1f3e055a27 Mon Sep 17 00:00:00 2001 From: Jonas Karlsson Date: Wed, 9 Mar 2022 22:19:10 +0100 Subject: [PATCH 15/16] Fix 'i >= 0' always true bug If 'disk_filename' does not contain a dot (.) then 'i' would overflow. Making 'i' an int makes sure the for loop works as intended. --- code/Common/ZipArchiveIOSystem.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/code/Common/ZipArchiveIOSystem.cpp b/code/Common/ZipArchiveIOSystem.cpp index c322b140f..ba90ae9b3 100644 --- a/code/Common/ZipArchiveIOSystem.cpp +++ b/code/Common/ZipArchiveIOSystem.cpp @@ -122,7 +122,7 @@ voidpf IOSystem2Unzip::open(voidpf opaque, const char *filename, int mode) { voidpf IOSystem2Unzip::opendisk(voidpf opaque, voidpf stream, uint32_t number_disk, int mode) { ZipFile *io_stream = (ZipFile *)stream; voidpf ret = NULL; - size_t i; + int i; char *disk_filename = (char*)malloc(io_stream->m_Filename.length() + 1); strncpy(disk_filename, io_stream->m_Filename.c_str(), io_stream->m_Filename.length() + 1); @@ -130,7 +130,7 @@ voidpf IOSystem2Unzip::opendisk(voidpf opaque, voidpf stream, uint32_t number_di { if (disk_filename[i] != '.') continue; - snprintf(&disk_filename[i], io_stream->m_Filename.length() - i, ".z%02u", number_disk + 1); + snprintf(&disk_filename[i], io_stream->m_Filename.length() - size_t(i), ".z%02u", number_disk + 1); break; } From 47f004517fca061e89896f2244be32fe6a506eb9 Mon Sep 17 00:00:00 2001 From: Kim Kulling Date: Thu, 10 Mar 2022 10:33:29 +0100 Subject: [PATCH 16/16] Add missing cast. --- code/Common/ZipArchiveIOSystem.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/Common/ZipArchiveIOSystem.cpp b/code/Common/ZipArchiveIOSystem.cpp index ba90ae9b3..e0c9883d2 100644 --- a/code/Common/ZipArchiveIOSystem.cpp +++ b/code/Common/ZipArchiveIOSystem.cpp @@ -126,7 +126,7 @@ voidpf IOSystem2Unzip::opendisk(voidpf opaque, voidpf stream, uint32_t number_di char *disk_filename = (char*)malloc(io_stream->m_Filename.length() + 1); strncpy(disk_filename, io_stream->m_Filename.c_str(), io_stream->m_Filename.length() + 1); - for (i = io_stream->m_Filename.length() - 1; i >= 0; i -= 1) + for (i = (int)io_stream->m_Filename.length() - 1; i >= 0; i -= 1) { if (disk_filename[i] != '.') continue;