Bump into V3, prepare myself for patching meshbuffer to use rh/lh flag
MODIFY
include/IrrCompileConfig.h
include/IrrCompileConfig.h
@@ -336,7 +336,7 @@ currently only supports zip archives, though. */
#endif
-#define _IRR_BAW_FORMAT_VERSION 2
+#define _IRR_BAW_FORMAT_VERSION 3
//! @see @ref CBlobsLoadingManager
#define _IRR_ADD_BLOB_SUPPORT(BlobClassName, EnumValue, Function, ...) \
@@ -345,13 +345,13 @@ case asset::Blob::EnumValue:\
//! Used inside CBlobsLoadingManager. Adds support of given blob types.
#define _IRR_SUPPORTED_BLOBS(Function, ...) \
-_IRR_ADD_BLOB_SUPPORT(RawBufferBlobV2, EBT_RAW_DATA_BUFFER, Function, __VA_ARGS__)\
-_IRR_ADD_BLOB_SUPPORT(TexturePathBlobV2, EBT_TEXTURE_PATH, Function, __VA_ARGS__)\
-_IRR_ADD_BLOB_SUPPORT(MeshBlobV2, EBT_MESH, Function, __VA_ARGS__)\
-_IRR_ADD_BLOB_SUPPORT(SkinnedMeshBlobV2, EBT_SKINNED_MESH, Function, __VA_ARGS__)\
-_IRR_ADD_BLOB_SUPPORT(MeshBufferBlobV2, EBT_MESH_BUFFER, Function, __VA_ARGS__)\
-_IRR_ADD_BLOB_SUPPORT(SkinnedMeshBufferBlobV2, EBT_SKINNED_MESH_BUFFER, Function, __VA_ARGS__)\
-_IRR_ADD_BLOB_SUPPORT(MeshDataFormatDescBlobV2, EBT_DATA_FORMAT_DESC, Function, __VA_ARGS__)\
-_IRR_ADD_BLOB_SUPPORT(FinalBoneHierarchyBlobV2, EBT_FINAL_BONE_HIERARCHY, Function, __VA_ARGS__)
+_IRR_ADD_BLOB_SUPPORT(RawBufferBlobV3, EBT_RAW_DATA_BUFFER, Function, __VA_ARGS__)\
+_IRR_ADD_BLOB_SUPPORT(TexturePathBlobV3, EBT_TEXTURE_PATH, Function, __VA_ARGS__)\
+_IRR_ADD_BLOB_SUPPORT(MeshBlobV3, EBT_MESH, Function, __VA_ARGS__)\
+_IRR_ADD_BLOB_SUPPORT(SkinnedMeshBlobV3, EBT_SKINNED_MESH, Function, __VA_ARGS__)\
+_IRR_ADD_BLOB_SUPPORT(MeshBufferBlobV3, EBT_MESH_BUFFER, Function, __VA_ARGS__)\
+_IRR_ADD_BLOB_SUPPORT(SkinnedMeshBufferBlobV3, EBT_SKINNED_MESH_BUFFER, Function, __VA_ARGS__)\
+_IRR_ADD_BLOB_SUPPORT(MeshDataFormatDescBlobV3, EBT_DATA_FORMAT_DESC, Function, __VA_ARGS__)\
+_IRR_ADD_BLOB_SUPPORT(FinalBoneHierarchyBlobV3, EBT_FINAL_BONE_HIERARCHY, Function, __VA_ARGS__)
#endif // __IRR_COMPILE_CONFIG_H_INCLUDED__

MODIFY
include/irr/asset/bawformat/CBAWFile.h
include/irr/asset/bawformat/CBAWFile.h
@@ -103,11 +103,11 @@ namespace asset
// ===============
// .baw VERSION
// ===============
- constexpr uint32_t CurrentBAWFormatVersion = 2u;
- using BlobHeaderV2 = BlobHeaderVn<CurrentBAWFormatVersion>;
- using BAWFileV2 = BAWFileVn<CurrentBAWFormatVersion>;
+ constexpr uint32_t CurrentBAWFormatVersion = 3u;
+ using BlobHeaderV3 = BlobHeaderVn<CurrentBAWFormatVersion>;
+ using BAWFileV3 = BAWFileVn<CurrentBAWFormatVersion>;
- using BlobHeaderLatest = BlobHeaderV2;
+ using BlobHeaderLatest = BlobHeaderV3;
bool encAes128gcm(const void* _input, size_t _inSize, void* _output, size_t _outSize, const unsigned char* _key, const unsigned char* _iv, void* _tag);
bool decAes128gcm(const void* _input, size_t _inSize, void* _output, size_t _outSize, const unsigned char* _key, const unsigned char* _iv, void* _tag);

MODIFY
include/irr/asset/bawformat/blobs/FinalBoneHierarchyBlob.h
include/irr/asset/bawformat/blobs/FinalBoneHierarchyBlob.h
@@ -90,8 +90,10 @@ static_assert(
"FinalBoneHierarchyBlobV2: Size of blob is not sum of its contents!"
);
+using FinalBoneHierarchyBlobV3 = FinalBoneHierarchyBlobV2;
+
template<>
-struct CorrespondingBlobTypeFor<CFinalBoneHierarchy> { typedef FinalBoneHierarchyBlobV2 type; };
+struct CorrespondingBlobTypeFor<CFinalBoneHierarchy> { typedef FinalBoneHierarchyBlobV3 type; };
}
} // irr::asset

MODIFY
include/irr/asset/bawformat/blobs/MeshBlob.h
include/irr/asset/bawformat/blobs/MeshBlob.h
@@ -40,9 +40,10 @@ static_assert(
using MeshBlobV1 = MeshBlobV0;
using MeshBlobV2 = MeshBlobV1;
+using MeshBlobV3 = MeshBlobV2;
template<>
-struct CorrespondingBlobTypeFor<ICPUMesh> { typedef MeshBlobV2 type; };
+struct CorrespondingBlobTypeFor<ICPUMesh> { typedef MeshBlobV3 type; };
}
} // irr::asset

MODIFY
include/irr/asset/bawformat/blobs/MeshBufferBlob.h
include/irr/asset/bawformat/blobs/MeshBufferBlob.h
@@ -45,10 +45,11 @@ static_assert(
using MeshBufferBlobV1 = MeshBufferBlobV0;
using MeshBufferBlobV2 = MeshBufferBlobV1;
+using MeshBufferBlobV3 = MeshBufferBlobV2;
template<>
-struct CorrespondingBlobTypeFor<ICPUMeshBuffer> { typedef MeshBufferBlobV2 type; };
+struct CorrespondingBlobTypeFor<ICPUMeshBuffer> { typedef MeshBufferBlobV3 type; };
}
} // irr::asset

MODIFY
include/irr/asset/bawformat/blobs/MeshDataFormatBlob.h
include/irr/asset/bawformat/blobs/MeshDataFormatBlob.h
@@ -47,14 +47,15 @@ static_assert(
);
using MeshDataFormatDescBlobV2 = MeshDataFormatDescBlobV1;
+using MeshDataFormatDescBlobV3 = MeshDataFormatDescBlobV2;
template<>
-struct CorrespondingBlobTypeFor<IMeshDataFormatDesc<ICPUBuffer> > { typedef MeshDataFormatDescBlobV2 type; };
+struct CorrespondingBlobTypeFor<IMeshDataFormatDesc<ICPUBuffer> > { typedef MeshDataFormatDescBlobV3 type; };
template<>
-inline size_t SizedBlob<FixedSizeBlob, MeshDataFormatDescBlobV2, IMeshDataFormatDesc<ICPUBuffer> >::calcBlobSizeForObj(const IMeshDataFormatDesc<ICPUBuffer>* _obj)
+inline size_t SizedBlob<FixedSizeBlob, MeshDataFormatDescBlobV3, IMeshDataFormatDesc<ICPUBuffer> >::calcBlobSizeForObj(const IMeshDataFormatDesc<ICPUBuffer>* _obj)
{
- return sizeof(MeshDataFormatDescBlobV2);
+ return sizeof(MeshDataFormatDescBlobV3);
}

MODIFY
include/irr/asset/bawformat/blobs/RawBufferBlob.h
include/irr/asset/bawformat/blobs/RawBufferBlob.h
@@ -22,9 +22,10 @@ struct IRR_FORCE_EBO RawBufferBlobV0 : TypedBlob<RawBufferBlobV0, ICPUBuffer>, V
using RawBufferBlobV1 = RawBufferBlobV0;
using RawBufferBlobV2 = RawBufferBlobV1;
+using RawBufferBlobV3 = RawBufferBlobV2;
template<>
-struct CorrespondingBlobTypeFor<ICPUBuffer> { typedef RawBufferBlobV2 type; };
+struct CorrespondingBlobTypeFor<ICPUBuffer> { typedef RawBufferBlobV3 type; };
}
} // irr::asset

MODIFY
include/irr/asset/bawformat/blobs/SkinnedMeshBlob.h
include/irr/asset/bawformat/blobs/SkinnedMeshBlob.h
@@ -37,9 +37,10 @@ static_assert(
using SkinnedMeshBlobV1 = SkinnedMeshBlobV0;
using SkinnedMeshBlobV2 = SkinnedMeshBlobV1;
+using SkinnedMeshBlobV3 = SkinnedMeshBlobV2;
template<>
-struct CorrespondingBlobTypeFor<ICPUSkinnedMesh> { typedef SkinnedMeshBlobV2 type; };
+struct CorrespondingBlobTypeFor<ICPUSkinnedMesh> { typedef SkinnedMeshBlobV3 type; };
}
} // irr::asset

MODIFY
include/irr/asset/bawformat/blobs/SkinnedMeshBufferBlob.h
include/irr/asset/bawformat/blobs/SkinnedMeshBufferBlob.h
@@ -46,9 +46,10 @@ static_assert(
using SkinnedMeshBufferBlobV1 = SkinnedMeshBufferBlobV0;
using SkinnedMeshBufferBlobV2 = SkinnedMeshBufferBlobV1;
+using SkinnedMeshBufferBlobV3 = SkinnedMeshBufferBlobV2;
template<>
-struct CorrespondingBlobTypeFor<ICPUSkinnedMeshBuffer> { typedef SkinnedMeshBufferBlobV2 type; };
+struct CorrespondingBlobTypeFor<ICPUSkinnedMeshBuffer> { typedef SkinnedMeshBufferBlobV3 type; };
}

MODIFY
include/irr/asset/bawformat/blobs/TexturePathBlob.h
include/irr/asset/bawformat/blobs/TexturePathBlob.h
@@ -24,9 +24,10 @@ struct IRR_FORCE_EBO TexturePathBlobV0 : TypedBlob<TexturePathBlobV0, ICPUTextur
using TexturePathBlobV1 = TexturePathBlobV0;
using TexturePathBlobV2 = TexturePathBlobV1;
+using TexturePathBlobV3 = TexturePathBlobV2;
template<>
-struct CorrespondingBlobTypeFor<video::IVirtualTexture> { typedef TexturePathBlobV2 type; };
+struct CorrespondingBlobTypeFor<video::IVirtualTexture> { typedef TexturePathBlobV3 type; };
}
} // irr::asset

MODIFY
src/irr/asset/CBAWMeshFileLoader.cpp
src/irr/asset/CBAWMeshFileLoader.cpp
@@ -231,6 +231,109 @@ bool CBAWMeshFileLoader::decompressLz4(void * _dst, size_t _dstSize, const void
return res >= 0;
}
+template<>
+io::IReadFile* CBAWMeshFileLoader::createConvertIntoVer_spec<3>(SContext& _ctx, io::IReadFile* _baw2file, asset::IAssetLoader::IAssetLoaderOverride* _override, const CommonDataTuple<2>& _common)
+{
+ uint32_t blobCnt{};
+ asset::legacyv2::BlobHeaderV2* headers = nullptr;
+ uint32_t* offsets = nullptr;
+ uint32_t baseOffsetv2{};
+ uint32_t baseOffsetv3{};
+ std::tie(blobCnt, headers, offsets, baseOffsetv2, baseOffsetv3) = _common;
+
+ io::CMemoryWriteFile* const baw3mem = new io::CMemoryWriteFile(0u, _baw2file->getFileName());
+
+ std::vector<uint32_t> newoffsets(blobCnt);
+ int32_t offsetDiff = 0;
+ for (uint32_t i = 0u; i < blobCnt; ++i)
+ {
+ asset::legacyv2::BlobHeaderV2& hdr = headers[i];
+ const uint32_t offset = offsets[i];
+ uint32_t& newoffset = newoffsets[i];
+
+ newoffset = offset + offsetDiff;
+
+ if (hdr.blobType == asset::Blob::EBT_FINAL_BONE_HIERARCHY)
+ {
+ const uint32_t offset = offsets[i];
+
+ uint8_t stackmem[1u << 10];
+ uint32_t attempt = 0u;
+ uint8_t decrKey[16];
+ size_t decrKeyLen = 16u;
+ void* blob = nullptr;
+ /* to state blob's/asset's hierarchy level we'd have to load (and possibly decrypt and decompress) the blob
+ however we don't need to do this here since we know format's version (baw v1) and so we can be sure that hierarchy level for FinalBoneHierarchy is 3 (won't be true for v2 to v3 conversion)
+ */
+ constexpr uint32_t FINALBONEHIERARCHY_HIERARCHY_LVL = 3u;
+ while (_override->getDecryptionKey(decrKey, decrKeyLen, attempt, _baw2file, "", genSubAssetCacheKey(_baw2file->getFileName().c_str(), hdr.handle), _ctx.inner, FINALBONEHIERARCHY_HIERARCHY_LVL))
+ {
+ if (!((hdr.compressionType & asset::Blob::EBCT_AES128_GCM) && decrKeyLen != 16u))
+ blob = tryReadBlobOnStack<asset::legacyv2::BlobHeaderV2>(SBlobData_t<asset::legacyv2::BlobHeaderV2>(&hdr, baseOffsetv2 + offset), _ctx, decrKey, stackmem, sizeof(stackmem));
+ if (blob)
+ break;
+ ++attempt;
+ }
+
+ // patch for meshbuffer blob
+ // TODO
+
+ offsetDiff += static_cast<int32_t>(hdr.blobSizeDecompr) - static_cast<int32_t>(hdr.effectiveSize());
+ hdr.compressionType = asset::Blob::EBCT_RAW;
+ core::XXHash_256(blob, hdr.blobSizeDecompr, hdr.blobHash);
+ hdr.blobSize = hdr.blobSizeDecompr;
+
+ if (blob)
+ _IRR_ALIGNED_FREE(blob);
+ }
+ }
+ uint64_t fileHeader[4]{ 0u, 0u, 0u, 2u/*baw v2*/ };
+ memcpy(fileHeader, BAWFileV3::HEADER_STRING, strlen(BAWFileV3::HEADER_STRING));
+ baw3mem->seek(0u);
+ baw3mem->write(fileHeader, sizeof(fileHeader));
+ baw3mem->write(&blobCnt, 4);
+ baw3mem->write(_ctx.iv, 16);
+ baw3mem->write(newoffsets.data(), newoffsets.size() * 4);
+ baw3mem->write(headers, blobCnt * sizeof(headers[0])); // blob header in v2 and in v3 is exact same thing, so we can do this
+
+ uint8_t stackmem[1u << 13]{};
+ size_t newFileSz = 0u;
+ for (uint32_t i = 0u; i < blobCnt; ++i)
+ {
+ uint32_t sz = headers[i].effectiveSize();
+ void* blob = nullptr;
+ if (headers[i].blobType == asset::Blob::EBT_FINAL_BONE_HIERARCHY)
+ {
+ sz = 0u;
+ }
+ else
+ {
+ _baw2file->seek(baseOffsetv2 + offsets[i]);
+ if (sz <= sizeof(stackmem))
+ blob = stackmem;
+ else
+ blob = _IRR_ALIGNED_MALLOC(sz, _IRR_SIMD_ALIGNMENT);
+
+ _baw2file->read(blob, sz);
+ }
+
+ baw3mem->seek(baseOffsetv2 + newoffsets[i]);
+ baw3mem->write(blob, sz);
+
+ if (headers[i].blobType != asset::Blob::EBT_DATA_FORMAT_DESC && blob != stackmem)
+ _IRR_ALIGNED_FREE(blob);
+
+ newFileSz = baseOffsetv3 + newoffsets[i] + sz;
+ }
+
+ _IRR_ALIGNED_FREE(offsets);
+ _IRR_ALIGNED_FREE(headers);
+
+ auto ret = new io::CMemoryReadFile(baw3mem->getPointer(), baw3mem->getSize(), _baw2file->getFileName());
+ baw3mem->drop();
+ return ret;
+}
+
//! These should be moved to some legacy baw loader .cpp file
template<>
io::IReadFile* CBAWMeshFileLoader::createConvertIntoVer_spec<2>(SContext& _ctx, io::IReadFile* _baw1file, asset::IAssetLoader::IAssetLoaderOverride* _override, const CommonDataTuple<1>& _common)
@@ -318,7 +421,7 @@ io::IReadFile* CBAWMeshFileLoader::createConvertIntoVer_spec<2>(SContext& _ctx,
}
}
uint64_t fileHeader[4] {0u, 0u, 0u, 2u/*baw v2*/};
- memcpy(fileHeader, BAWFileV2::HEADER_STRING, strlen(BAWFileV2::HEADER_STRING));
+ memcpy(fileHeader, asset::legacyv2::BAWFileV2::HEADER_STRING, strlen(asset::legacyv2::BAWFileV2::HEADER_STRING));
baw2mem->seek(0u);
baw2mem->write(fileHeader, sizeof(fileHeader));
baw2mem->write(&blobCnt, 4);

MODIFY
src/irr/asset/CBAWMeshFileLoader.h
src/irr/asset/CBAWMeshFileLoader.h
@@ -26,7 +26,7 @@ class IAssetManager;
class CBAWMeshFileLoader : public asset::IAssetLoader
{
- friend struct TypedBlob<TexturePathBlobV2, asset::ICPUTexture>; // needed for loading textures
+ friend struct TypedBlob<TexturePathBlobV3, asset::ICPUTexture>; // needed for loading textures
private:
template<typename HeaderT>
@@ -144,7 +144,8 @@ private:
{
case 0ull: return verifyFile<asset::legacyv0::BAWFileV0>(_ctx);
case 1ull: return verifyFile<asset::legacyv1::BAWFileV1>(_ctx);
- case 2ull: return verifyFile<asset::BAWFileV2>(_ctx);
+ case 2ull: return verifyFile<asset::legacyv2::BAWFileV2>(_ctx);
+ case 3ull: return verifyFile<asset::BAWFileV3>(_ctx);
default: return false;
}
}

MODIFY
src/irr/asset/CBAWMeshWriter.cpp
src/irr/asset/CBAWMeshWriter.cpp
@@ -47,13 +47,13 @@ struct LzmaMemMngmnt
void CBAWMeshWriter::exportAsBlob<ICPUMesh>(ICPUMesh* _obj, uint32_t _headerIdx, io::IWriteFile* _file, SContext& _ctx)
{
uint8_t stackData[1u<<14];
- auto data = MeshBlobV2::createAndTryOnStack(_obj, stackData, sizeof(stackData));
+ auto data = MeshBlobV3::createAndTryOnStack(_obj, stackData, sizeof(stackData));
const E_WRITER_FLAGS flags = _ctx.writerOverride->getAssetWritingFlags(_ctx.inner, _obj, 0u);
const uint8_t* encrPwd = nullptr;
_ctx.writerOverride->getEncryptionKey(encrPwd, _ctx.inner, _obj, 0u);
const float comprLvl = _ctx.writerOverride->getAssetCompressionLevel(_ctx.inner, _obj, 0u);
- tryWrite(data, _file, _ctx, MeshBlobV2::calcBlobSizeForObj(_obj), _headerIdx, flags, encrPwd, comprLvl);
+ tryWrite(data, _file, _ctx, MeshBlobV3::calcBlobSizeForObj(_obj), _headerIdx, flags, encrPwd, comprLvl);
if ((uint8_t*)data != stackData)
_IRR_ALIGNED_FREE(data);
@@ -62,13 +62,13 @@ struct LzmaMemMngmnt
void CBAWMeshWriter::exportAsBlob<ICPUSkinnedMesh>(ICPUSkinnedMesh* _obj, uint32_t _headerIdx, io::IWriteFile* _file, SContext& _ctx)
{
uint8_t stackData[1u << 14];
- SkinnedMeshBlobV2* data = SkinnedMeshBlobV1::createAndTryOnStack(_obj,stackData,sizeof(stackData));
+ SkinnedMeshBlobV3* data = SkinnedMeshBlobV3::createAndTryOnStack(_obj,stackData,sizeof(stackData));
const E_WRITER_FLAGS flags = _ctx.writerOverride->getAssetWritingFlags(_ctx.inner, _obj, 0u);
const uint8_t* encrPwd = nullptr;
_ctx.writerOverride->getEncryptionKey(encrPwd, _ctx.inner, _obj, 0u);
const float comprLvl = _ctx.writerOverride->getAssetCompressionLevel(_ctx.inner, _obj, 0u);
- tryWrite(data, _file, _ctx, SkinnedMeshBlobV2::calcBlobSizeForObj(_obj), _headerIdx, flags, encrPwd, comprLvl);
+ tryWrite(data, _file, _ctx, SkinnedMeshBlobV3::calcBlobSizeForObj(_obj), _headerIdx, flags, encrPwd, comprLvl);
if ((uint8_t*)data != stackData)
_IRR_ALIGNED_FREE(data);
@@ -76,7 +76,7 @@ struct LzmaMemMngmnt
template<>
void CBAWMeshWriter::exportAsBlob<ICPUMeshBuffer>(ICPUMeshBuffer* _obj, uint32_t _headerIdx, io::IWriteFile* _file, SContext& _ctx)
{
- MeshBufferBlobV2 data(_obj);
+ MeshBufferBlobV3 data(_obj);
const E_WRITER_FLAGS flags = _ctx.writerOverride->getAssetWritingFlags(_ctx.inner, _obj, 1u);
const uint8_t* encrPwd = nullptr;
@@ -87,7 +87,7 @@ struct LzmaMemMngmnt
template<>
void CBAWMeshWriter::exportAsBlob<ICPUSkinnedMeshBuffer>(ICPUSkinnedMeshBuffer* _obj, uint32_t _headerIdx, io::IWriteFile* _file, SContext& _ctx)
{
- SkinnedMeshBufferBlobV2 data(_obj);
+ SkinnedMeshBufferBlobV3 data(_obj);
const E_WRITER_FLAGS flags = _ctx.writerOverride->getAssetWritingFlags(_ctx.inner, _obj, 1u);
const uint8_t* encrPwd = nullptr;
@@ -115,9 +115,9 @@ struct LzmaMemMngmnt
void CBAWMeshWriter::exportAsBlob<CFinalBoneHierarchy>(CFinalBoneHierarchy* _obj, uint32_t _headerIdx, io::IWriteFile* _file, SContext& _ctx)
{
uint8_t stackData[1u<<14]; // 16kB
- auto data = FinalBoneHierarchyBlobV2::createAndTryOnStack(_obj,stackData,sizeof(stackData));
+ auto data = FinalBoneHierarchyBlobV3::createAndTryOnStack(_obj,stackData,sizeof(stackData));
- tryWrite(data, _file, _ctx, FinalBoneHierarchyBlobV2::calcBlobSizeForObj(_obj), _headerIdx, EWF_NONE);
+ tryWrite(data, _file, _ctx, FinalBoneHierarchyBlobV3::calcBlobSizeForObj(_obj), _headerIdx, EWF_NONE);
if ((uint8_t*)data != stackData)
_IRR_ALIGNED_FREE(data);
@@ -125,7 +125,7 @@ struct LzmaMemMngmnt
template<>
void CBAWMeshWriter::exportAsBlob<IMeshDataFormatDesc<ICPUBuffer> >(IMeshDataFormatDesc<ICPUBuffer>* _obj, uint32_t _headerIdx, io::IWriteFile* _file, SContext& _ctx)
{
- MeshDataFormatDescBlobV2 data(_obj);
+ MeshDataFormatDescBlobV3 data(_obj);
tryWrite(&data, _file, _ctx, sizeof(data), _headerIdx, EWF_NONE);
}
@@ -154,7 +154,7 @@ struct LzmaMemMngmnt
const ICPUMesh* mesh = static_cast<const ICPUMesh*>(_params.rootAsset);
constexpr uint32_t FILE_HEADER_SIZE = 32;
- static_assert(FILE_HEADER_SIZE == sizeof(BAWFileV2::fileHeader), "BAW header is not 32 bytes long!");
+ static_assert(FILE_HEADER_SIZE == sizeof(BAWFileV3::fileHeader), "BAW header is not 32 bytes long!");
uint64_t header[4];
memcpy(header, BAW_FILE_HEADER, FILE_HEADER_SIZE);
@@ -165,7 +165,7 @@ struct LzmaMemMngmnt
SContext ctx{ IAssetWriter::SAssetWriteContext{_params, _file}, _override }; // context of this call of `writeMesh`
const uint32_t numOfInternalBlobs = genHeaders(mesh, ctx);
- const uint32_t OFFSETS_FILE_OFFSET = FILE_HEADER_SIZE + sizeof(uint32_t) + sizeof(BAWFileV2::iv);
+ const uint32_t OFFSETS_FILE_OFFSET = FILE_HEADER_SIZE + sizeof(uint32_t) + sizeof(BAWFileV3::iv);
const uint32_t HEADERS_FILE_OFFSET = OFFSETS_FILE_OFFSET + numOfInternalBlobs * sizeof(ctx.offsets[0]);
ctx.offsets.resize(numOfInternalBlobs);

MODIFY
src/irr/asset/bawformat/legacy/CBAWLegacy.h
src/irr/asset/bawformat/legacy/CBAWLegacy.h
@@ -127,6 +127,16 @@ using BlobHeaderV1 = BlobHeaderVn<1>;
using FinalBoneHierarchyBlobV1 = legacyv0::FinalBoneHierarchyBlobV0;
+}
+
+namespace legacyv2
+{
+
+
+using BAWFileV2 = BAWFileVn<2>;
+using BlobHeaderV2 = BlobHeaderVn<2>;
+
+
}
}

Bump into V3, prepare myself for patching meshbuffer to use rh/lh flag