now can read CKMesh without memory issue
This commit is contained in:
parent
678529a664
commit
d381369ed6
|
@ -17,7 +17,7 @@ namespace LibCmo::CK2 {
|
|||
// get ext and guid to find correct guid
|
||||
CKCHAR filerawext[4];
|
||||
CKGUID fileguid;
|
||||
chk->ReadNoSizeBuffer(CKSizeof(filerawext), filerawext);
|
||||
chk->ReadAndFillBuffer(filerawext, CKSizeof(filerawext));
|
||||
chk->ReadStruct(fileguid);
|
||||
CKFileExtension fileext(filerawext);
|
||||
auto reader = DataHandlers::CKBitmapHandler::GetBitmapHandlerWrapper(fileext, fileguid);
|
||||
|
@ -56,7 +56,7 @@ namespace LibCmo::CK2 {
|
|||
VxMath::VxDoAlphaBlit(slot, static_cast<CKBYTE>(globalalpha));
|
||||
} else {
|
||||
auto alphabuf = chk->ReadBufferWrapper();
|
||||
VxMath::VxDoAlphaBlit(slot, reinterpret_cast<CKBYTE*>(alphabuf.get()));
|
||||
VxMath::VxDoAlphaBlit(slot, reinterpret_cast<const CKBYTE*>(alphabuf.get()));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -79,7 +79,6 @@ namespace LibCmo::CK2 {
|
|||
|
||||
// read RGBA buffer
|
||||
CKStateChunk::Buffer_t redBuffer, greenBuffer, blueBuffer, alphaBuffer;
|
||||
CKDWORD bufsize;
|
||||
CKDWORD bufopt;
|
||||
chk->ReadStruct(bufopt);
|
||||
bufopt &= 0xFu;
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
#include "ObjImpls/CK3dObject.hpp"
|
||||
#include "ObjImpls/CKTexture.hpp"
|
||||
#include "ObjImpls/CKMaterial.hpp"
|
||||
#include "ObjImpls/CKMesh.hpp"
|
||||
|
||||
namespace LibCmo::CK2 {
|
||||
|
||||
|
@ -414,6 +415,7 @@ CKClassRegister(cid, parentCid, \
|
|||
EasyClassReg(ObjImpls::CK3dObject, CK_CLASSID::CKCID_3DOBJECT, CK_CLASSID::CKCID_3DENTITY, "3D Object");
|
||||
EasyClassReg(ObjImpls::CKTexture, CK_CLASSID::CKCID_TEXTURE, CK_CLASSID::CKCID_BEOBJECT, "Texture");
|
||||
EasyClassReg(ObjImpls::CKMaterial, CK_CLASSID::CKCID_MATERIAL, CK_CLASSID::CKCID_BEOBJECT, "Material");
|
||||
EasyClassReg(ObjImpls::CKMesh, CK_CLASSID::CKCID_MESH, CK_CLASSID::CKCID_BEOBJECT, "Mesh");
|
||||
|
||||
#undef EasyClassReg
|
||||
#undef EasyClassRegWithNotify
|
||||
|
|
|
@ -65,7 +65,7 @@ namespace LibCmo::CK2 {
|
|||
CKStateChunk* m_Host;
|
||||
CKDWORD m_ConsumedSize;
|
||||
};
|
||||
|
||||
|
||||
class BufferDeleter {
|
||||
public:
|
||||
BufferDeleter() : m_Host(nullptr), m_BufSize(0) {}
|
||||
|
@ -333,73 +333,89 @@ namespace LibCmo::CK2 {
|
|||
/*
|
||||
Buffer related function implements:
|
||||
|
||||
ReadBuffer(void**) Read Byte based size. -> ReadBuffer
|
||||
ReadAndFillBuffer(int, void*) User give Byte based size. -> ReadNoSizeBuffer
|
||||
ReadAndFillBuffer(void*) Read Byte based size. -> ReadBuffer
|
||||
ReadAndFillBuffer_LEndian(int, void*) User give Byte based size. -> ReadNoSizeBuffer
|
||||
ReadAndFillBuffer_LEndian(void*) Read Byte based size. -> ReadBuffer
|
||||
ReadAndFillBuffer_LEndian16(int, void*) User give Byte based size. -> ReadNoSizeBuffer
|
||||
ReadAndFillBuffer_LEndian16(void*) Read Byte based size. -> ReadBuffer
|
||||
ReadBuffer(void**) Read Byte based size. -> ReadAndCopyBuffer(void**, CKDWORD*)
|
||||
ReadAndFillBuffer(int, void*) User give Byte based size. -> ReadBuffer(const void**, CKDWORD)
|
||||
ReadAndFillBuffer(void*) Read Byte based size. -> ReadBuffer(const void**, CKDWORD*)
|
||||
ReadAndFillBuffer_LEndian(int, void*) User give Byte based size. -> ReadBuffer(const void**, CKDWORD)
|
||||
ReadAndFillBuffer_LEndian(void*) Read Byte based size. -> ReadBuffer(const void**, CKDWORD*)
|
||||
ReadAndFillBuffer_LEndian16(int, void*) User give Byte based size. -> ReadBuffer(const void**, CKDWORD)
|
||||
ReadAndFillBuffer_LEndian16(void*) Read Byte based size. -> ReadBuffer(const void**, CKDWORD*)
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Read a buffer with unknow size (order user specific it).
|
||||
* @param size_in_byte[in] The size of buffer.
|
||||
* @param allocatedBuf[out] Buffer for filling.
|
||||
* @return true if success.
|
||||
* @remark
|
||||
* + Following original Virtools functions can use this function to implement:
|
||||
* - ReadAndFillBuffer(int, void*)
|
||||
* - ReadAndFillBuffer_LEndian(int, void*)
|
||||
* - ReadAndFillBuffer_LEndian16(int, void*)
|
||||
*/
|
||||
bool ReadNoSizeBuffer(CKDWORD size_in_byte, void* allocatedBuf);
|
||||
/**
|
||||
* @brief Read a buffer with knowen size stored in chunk.
|
||||
* @param buf[out] a pointer to the pointer receiving data start address.
|
||||
* @param len_in_byte[out] a pointer to the variable receiving the length of gotten buffer.
|
||||
* @return true if success.
|
||||
* @brief Read buffer and copy it.
|
||||
* The copied buffer and the size of buffer will be returned to caller.
|
||||
* Caller should free the buffer by calling CKStateChunk::DeleteBuffer(void*).
|
||||
* @param ppData[out] The pointer to pointer holding the new copied data.
|
||||
* @param size_in_byte[out] Set to the size of buffer when success.
|
||||
* @return True if success.
|
||||
* @remark
|
||||
* + Following original Virtools functions can use this function to implement:
|
||||
* - ReadBuffer(void**)
|
||||
* - ReadAndFillBuffer(void*)
|
||||
* - ReadAndFillBuffer_LEndian(void*)
|
||||
* - ReadAndFillBuffer_LEndian16(void*)
|
||||
* + The created buffer should be freed by DeleteBuffer().
|
||||
*/
|
||||
bool ReadBuffer(void** buf, CKDWORD* len_in_byte);
|
||||
|
||||
bool ReadBuffer(void** ppData, CKDWORD* size_in_byte);
|
||||
/**
|
||||
* @brief Free the buffer allocated by CKStateChunk reading functions.
|
||||
* @param buf[in] The buffer need to be free.
|
||||
* @see ReadBuffer
|
||||
*/
|
||||
void DeleteBuffer(const void* buf);
|
||||
|
||||
/**
|
||||
* @brief A RAII wrapper for ReadBuffer and DeleteBuffer
|
||||
* @param uptr The pointer to unique_ptr receiving data.
|
||||
* @param len_in_byte The size of gotten buffer.
|
||||
* @return A buffer with RAII feature (more like std::unique_ptr).
|
||||
* @remark
|
||||
* + The return value is more like std::unique_ptr but it have more features.
|
||||
* + If Buffer_t::GetPtr return nullptr, it mean this function is failed.
|
||||
* + Use Buffer_t::GetSize to get the size of buffer.
|
||||
* + You can use Buffer_t::Reset to force free the return value.
|
||||
* @example
|
||||
* ```
|
||||
* Buffer_t buf = ReadBufferWrapper(1919810);
|
||||
* if (buf.GetPtr() == nullptr) {
|
||||
* // failed
|
||||
* } else {
|
||||
* stuff(buf); // do some operation...
|
||||
* buf.SetSize(114514); // i only consume these bytes.
|
||||
* buf.Reset(); // immediately free it.
|
||||
* }
|
||||
* ```
|
||||
* @brief A wrapper for ReadAndCopyBuffer(void**, CKDWORD*)
|
||||
* @return
|
||||
*/
|
||||
Buffer_t ReadBufferWrapper();
|
||||
|
||||
/**
|
||||
* @brief Read buffer and fill user struct.
|
||||
* The size of buffer will be read from CKStateChunk internally and return to caller.
|
||||
* @param pData[out] The pointer holding the data.
|
||||
* @return True if success.
|
||||
* @remark
|
||||
* + Following original Virtools functions can use this function to implement:
|
||||
* - ReadAndFillBuffer(void*)
|
||||
* - ReadAndFillBuffer_LEndian(void*)
|
||||
* - ReadAndFillBuffer_LEndian16(void*)
|
||||
*/
|
||||
bool ReadAndFillBuffer(void* pData);
|
||||
/**
|
||||
* @brief Read buffer and fill user struct.
|
||||
* The size of buffer is provided by user.
|
||||
* @param pData[out] The pointer holding the data.
|
||||
* @param size_in_byte[in] The size of data which you want to read in byte unit
|
||||
* @return True if success.
|
||||
* @remark
|
||||
* + Following original Virtools functions can use this function to implement:
|
||||
* - ReadAndFillBuffer(int, void*)
|
||||
* - ReadAndFillBuffer_LEndian(int, void*)
|
||||
* - ReadAndFillBuffer_LEndian16(int, void*)
|
||||
*/
|
||||
bool ReadAndFillBuffer(void* pData, CKDWORD size_in_byte);
|
||||
|
||||
///**
|
||||
// * @brief A RAII wrapper for ReadBuffer and DeleteBuffer
|
||||
// * @param uptr The pointer to unique_ptr receiving data.
|
||||
// * @param len_in_byte The size of gotten buffer.
|
||||
// * @return A buffer with RAII feature (more like std::unique_ptr).
|
||||
// * @remark
|
||||
// * + The return value is more like std::unique_ptr but it have more features.
|
||||
// * + If Buffer_t::GetPtr return nullptr, it mean this function is failed.
|
||||
// * + Use Buffer_t::GetSize to get the size of buffer.
|
||||
// * + You can use Buffer_t::Reset to force free the return value.
|
||||
// * @example
|
||||
// * ```
|
||||
// * Buffer_t buf = ReadBufferWrapper(1919810);
|
||||
// * if (buf.GetPtr() == nullptr) {
|
||||
// * // failed
|
||||
// * } else {
|
||||
// * stuff(buf); // do some operation...
|
||||
// * buf.SetSize(114514); // i only consume these bytes.
|
||||
// * buf.Reset(); // immediately free it.
|
||||
// * }
|
||||
// * ```
|
||||
//*/
|
||||
//Buffer_t ReadBufferWrapper();
|
||||
|
||||
/* ========== Sequence Functions ==========*/
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -289,57 +289,87 @@ namespace LibCmo::CK2 {
|
|||
|
||||
/* ========== Buffer Functions ==========*/
|
||||
|
||||
bool CKStateChunk::ReadNoSizeBuffer(CKDWORD size_in_byte, void* allocatedBuf) {
|
||||
if (allocatedBuf == nullptr) return false;
|
||||
return this->ReadByteData(allocatedBuf, size_in_byte);
|
||||
}
|
||||
bool CKStateChunk::ReadBuffer(void** ppData, CKDWORD* size_in_byte) {
|
||||
if (ppData == nullptr || size_in_byte == nullptr) return false;
|
||||
*ppData = nullptr;
|
||||
*size_in_byte = 0;
|
||||
|
||||
bool CKStateChunk::ReadBuffer(void** buf, CKDWORD* len_in_byte) {
|
||||
if (buf == nullptr || len_in_byte == nullptr) return false;
|
||||
|
||||
// get buffer size.
|
||||
CKDWORD bufByteSize = 0u;
|
||||
if (!this->ReadStruct(bufByteSize)) {
|
||||
*buf = nullptr;
|
||||
*len_in_byte = 0;
|
||||
// read size first
|
||||
if (!this->ReadStruct(size_in_byte)) {
|
||||
return false;
|
||||
}
|
||||
*len_in_byte = bufByteSize;
|
||||
|
||||
// special treat for zero length buffer
|
||||
if (bufByteSize == 0) {
|
||||
*buf = nullptr;
|
||||
// if it is empty buffer, create a fake buffer
|
||||
// and simply return it.
|
||||
if (*size_in_byte == 0) {
|
||||
*ppData = new CKBYTE[1];
|
||||
return true;
|
||||
}
|
||||
|
||||
// create buffer
|
||||
*buf = new CKBYTE[bufByteSize];
|
||||
|
||||
// read data
|
||||
if (!this->ReadByteData(*buf, bufByteSize)) {
|
||||
this->DeleteBuffer(*buf);
|
||||
*buf = nullptr;
|
||||
*len_in_byte = 0;
|
||||
// use LockReadBuffer to get pointer
|
||||
auto locker = LockReadBufferWrapper(*size_in_byte);
|
||||
if (locker == nullptr) {
|
||||
*size_in_byte = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
// copy data and unlock buffer
|
||||
*ppData = new CKBYTE[*size_in_byte];
|
||||
std::memcpy(*ppData, locker.get(), *size_in_byte);
|
||||
locker.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CKStateChunk::DeleteBuffer(const void* buf) {
|
||||
if (buf == nullptr) return;
|
||||
delete[] reinterpret_cast<const CKBYTE*>(buf);
|
||||
}
|
||||
|
||||
CKStateChunk::Buffer_t CKStateChunk::ReadBufferWrapper() {
|
||||
void* bufcache = nullptr;
|
||||
CKDWORD len_in_byte;
|
||||
bool ret = ReadBuffer(&bufcache, &len_in_byte);
|
||||
if (ret) {
|
||||
return Buffer_t(bufcache, BufferDeleter(this, len_in_byte));
|
||||
} else {
|
||||
void* cache;
|
||||
CKDWORD size;
|
||||
if (!ReadBuffer(&cache, &size)) {
|
||||
return Buffer_t();
|
||||
}
|
||||
return Buffer_t(cache, BufferDeleter(this, size));
|
||||
}
|
||||
|
||||
bool CKStateChunk::ReadAndFillBuffer(void* pData) {
|
||||
if (pData == nullptr) return false;
|
||||
|
||||
// get buffer size.
|
||||
CKDWORD size_in_byte;
|
||||
if (!this->ReadStruct(size_in_byte)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// use LockReadBuffer to get pointer
|
||||
// this step can process zero length buffer
|
||||
// so we do not treat it specially
|
||||
auto locker = LockReadBufferWrapper(size_in_byte);
|
||||
if (locker == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// then copy the data
|
||||
std::memcpy(pData, locker.get(), size_in_byte);
|
||||
locker.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CKStateChunk::ReadAndFillBuffer(void* pData, CKDWORD size_in_byte) {
|
||||
if (pData == nullptr) return false;
|
||||
|
||||
// directly use LockReadBuffer to get pointer
|
||||
auto locker = LockReadBufferWrapper(size_in_byte);
|
||||
if (locker == nullptr) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// then copy the data
|
||||
std::memcpy(pData, locker.get(), size_in_byte);
|
||||
locker.reset();
|
||||
return true;
|
||||
}
|
||||
|
||||
/* ========== Sequence Functions ==========*/
|
||||
|
|
|
@ -79,14 +79,16 @@ namespace LibCmo::CK2::ObjImpls {
|
|||
// read and set vertex count
|
||||
CKDWORD vertexCount;
|
||||
chunk->ReadStruct(vertexCount);
|
||||
SetVertexCount(vertexCount);
|
||||
|
||||
if (vertexCount != 0) {
|
||||
// read save flags
|
||||
chunk->ReadStruct(saveflags);
|
||||
|
||||
// read size in dword
|
||||
// read size in dword (including it self)
|
||||
CKDWORD sizeInDword;
|
||||
chunk->ReadStruct(sizeInDword);
|
||||
--sizeInDword; // remove self.
|
||||
|
||||
// lock read buffer
|
||||
auto buf = chunk->LockReadBufferWrapper(sizeInDword * CKSizeof(CKDWORD));
|
||||
|
@ -211,7 +213,14 @@ namespace LibCmo::CK2::ObjImpls {
|
|||
chunk->ReadStruct(lineCount);
|
||||
SetLineCount(lineCount);
|
||||
|
||||
chunk->ReadNoSizeBuffer(lineCount * 2 )
|
||||
chunk->ReadAndFillBuffer(m_LineIndices.data(), CKSizeof(CKWORD) * lineCount * 2);
|
||||
}
|
||||
|
||||
// build normals
|
||||
if (EnumsHelper::Has(saveflags, VertexSaveFlags::NoNormal)) {
|
||||
BuildNormals();
|
||||
} else {
|
||||
BuildFaceNormals();
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -227,6 +236,10 @@ namespace LibCmo::CK2::ObjImpls {
|
|||
SetLineCount(0);
|
||||
}
|
||||
|
||||
void CKMesh::BuildNormals() {}
|
||||
|
||||
void CKMesh::BuildFaceNormals() {}
|
||||
|
||||
#pragma region Vertex Section
|
||||
|
||||
CKDWORD CKMesh::GetVertexCount() {
|
||||
|
|
|
@ -109,7 +109,7 @@ namespace LibCmo::VxMath {
|
|||
}
|
||||
}
|
||||
|
||||
void VxDoAlphaBlit(VxImageDescEx* dst_desc, CKBYTE* AlphaValues) {
|
||||
void VxDoAlphaBlit(VxImageDescEx* dst_desc, const CKBYTE* AlphaValues) {
|
||||
if (dst_desc == nullptr) return;
|
||||
|
||||
CKDWORD* pixels = dst_desc->GetMutablePixels();
|
||||
|
|
|
@ -81,7 +81,7 @@ namespace LibCmo::VxMath {
|
|||
* @param AlphaValues[in] A BYTE array containing the alpha values for each pixel. This array should be allocated to Width*Height bytes.
|
||||
* @remark If the destination image does not have alpha information the function returns immediatly.
|
||||
*/
|
||||
void VxDoAlphaBlit(VxImageDescEx* dst_desc, CKBYTE* AlphaValues);
|
||||
void VxDoAlphaBlit(VxImageDescEx* dst_desc, const CKBYTE* AlphaValues);
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user