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
|
// get ext and guid to find correct guid
|
||||||
CKCHAR filerawext[4];
|
CKCHAR filerawext[4];
|
||||||
CKGUID fileguid;
|
CKGUID fileguid;
|
||||||
chk->ReadNoSizeBuffer(CKSizeof(filerawext), filerawext);
|
chk->ReadAndFillBuffer(filerawext, CKSizeof(filerawext));
|
||||||
chk->ReadStruct(fileguid);
|
chk->ReadStruct(fileguid);
|
||||||
CKFileExtension fileext(filerawext);
|
CKFileExtension fileext(filerawext);
|
||||||
auto reader = DataHandlers::CKBitmapHandler::GetBitmapHandlerWrapper(fileext, fileguid);
|
auto reader = DataHandlers::CKBitmapHandler::GetBitmapHandlerWrapper(fileext, fileguid);
|
||||||
|
@ -56,7 +56,7 @@ namespace LibCmo::CK2 {
|
||||||
VxMath::VxDoAlphaBlit(slot, static_cast<CKBYTE>(globalalpha));
|
VxMath::VxDoAlphaBlit(slot, static_cast<CKBYTE>(globalalpha));
|
||||||
} else {
|
} else {
|
||||||
auto alphabuf = chk->ReadBufferWrapper();
|
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
|
// read RGBA buffer
|
||||||
CKStateChunk::Buffer_t redBuffer, greenBuffer, blueBuffer, alphaBuffer;
|
CKStateChunk::Buffer_t redBuffer, greenBuffer, blueBuffer, alphaBuffer;
|
||||||
CKDWORD bufsize;
|
|
||||||
CKDWORD bufopt;
|
CKDWORD bufopt;
|
||||||
chk->ReadStruct(bufopt);
|
chk->ReadStruct(bufopt);
|
||||||
bufopt &= 0xFu;
|
bufopt &= 0xFu;
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "ObjImpls/CK3dObject.hpp"
|
#include "ObjImpls/CK3dObject.hpp"
|
||||||
#include "ObjImpls/CKTexture.hpp"
|
#include "ObjImpls/CKTexture.hpp"
|
||||||
#include "ObjImpls/CKMaterial.hpp"
|
#include "ObjImpls/CKMaterial.hpp"
|
||||||
|
#include "ObjImpls/CKMesh.hpp"
|
||||||
|
|
||||||
namespace LibCmo::CK2 {
|
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::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::CKTexture, CK_CLASSID::CKCID_TEXTURE, CK_CLASSID::CKCID_BEOBJECT, "Texture");
|
||||||
EasyClassReg(ObjImpls::CKMaterial, CK_CLASSID::CKCID_MATERIAL, CK_CLASSID::CKCID_BEOBJECT, "Material");
|
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 EasyClassReg
|
||||||
#undef EasyClassRegWithNotify
|
#undef EasyClassRegWithNotify
|
||||||
|
|
|
@ -65,7 +65,7 @@ namespace LibCmo::CK2 {
|
||||||
CKStateChunk* m_Host;
|
CKStateChunk* m_Host;
|
||||||
CKDWORD m_ConsumedSize;
|
CKDWORD m_ConsumedSize;
|
||||||
};
|
};
|
||||||
|
|
||||||
class BufferDeleter {
|
class BufferDeleter {
|
||||||
public:
|
public:
|
||||||
BufferDeleter() : m_Host(nullptr), m_BufSize(0) {}
|
BufferDeleter() : m_Host(nullptr), m_BufSize(0) {}
|
||||||
|
@ -333,73 +333,89 @@ namespace LibCmo::CK2 {
|
||||||
/*
|
/*
|
||||||
Buffer related function implements:
|
Buffer related function implements:
|
||||||
|
|
||||||
ReadBuffer(void**) Read Byte based size. -> ReadBuffer
|
ReadBuffer(void**) Read Byte based size. -> ReadAndCopyBuffer(void**, CKDWORD*)
|
||||||
ReadAndFillBuffer(int, void*) User give Byte based size. -> ReadNoSizeBuffer
|
ReadAndFillBuffer(int, void*) User give Byte based size. -> ReadBuffer(const void**, CKDWORD)
|
||||||
ReadAndFillBuffer(void*) Read Byte based size. -> ReadBuffer
|
ReadAndFillBuffer(void*) Read Byte based size. -> ReadBuffer(const void**, CKDWORD*)
|
||||||
ReadAndFillBuffer_LEndian(int, void*) User give Byte based size. -> ReadNoSizeBuffer
|
ReadAndFillBuffer_LEndian(int, void*) User give Byte based size. -> ReadBuffer(const void**, CKDWORD)
|
||||||
ReadAndFillBuffer_LEndian(void*) Read Byte based size. -> ReadBuffer
|
ReadAndFillBuffer_LEndian(void*) Read Byte based size. -> ReadBuffer(const void**, CKDWORD*)
|
||||||
ReadAndFillBuffer_LEndian16(int, void*) User give Byte based size. -> ReadNoSizeBuffer
|
ReadAndFillBuffer_LEndian16(int, void*) User give Byte based size. -> ReadBuffer(const void**, CKDWORD)
|
||||||
ReadAndFillBuffer_LEndian16(void*) Read Byte based size. -> ReadBuffer
|
ReadAndFillBuffer_LEndian16(void*) Read Byte based size. -> ReadBuffer(const void**, CKDWORD*)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Read a buffer with unknow size (order user specific it).
|
* @brief Read buffer and copy it.
|
||||||
* @param size_in_byte[in] The size of buffer.
|
* The copied buffer and the size of buffer will be returned to caller.
|
||||||
* @param allocatedBuf[out] Buffer for filling.
|
* Caller should free the buffer by calling CKStateChunk::DeleteBuffer(void*).
|
||||||
* @return true if success.
|
* @param ppData[out] The pointer to pointer holding the new copied data.
|
||||||
* @remark
|
* @param size_in_byte[out] Set to the size of buffer when success.
|
||||||
* + Following original Virtools functions can use this function to implement:
|
* @return True if success.
|
||||||
* - 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.
|
|
||||||
* @remark
|
* @remark
|
||||||
* + Following original Virtools functions can use this function to implement:
|
* + Following original Virtools functions can use this function to implement:
|
||||||
* - ReadBuffer(void**)
|
* - 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.
|
* @brief Free the buffer allocated by CKStateChunk reading functions.
|
||||||
* @param buf[in] The buffer need to be free.
|
* @param buf[in] The buffer need to be free.
|
||||||
* @see ReadBuffer
|
* @see ReadBuffer
|
||||||
*/
|
*/
|
||||||
void DeleteBuffer(const void* buf);
|
void DeleteBuffer(const void* buf);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A RAII wrapper for ReadBuffer and DeleteBuffer
|
* @brief A wrapper for ReadAndCopyBuffer(void**, CKDWORD*)
|
||||||
* @param uptr The pointer to unique_ptr receiving data.
|
* @return
|
||||||
* @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();
|
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 ==========*/
|
/* ========== Sequence Functions ==========*/
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -289,57 +289,87 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
/* ========== Buffer Functions ==========*/
|
/* ========== Buffer Functions ==========*/
|
||||||
|
|
||||||
bool CKStateChunk::ReadNoSizeBuffer(CKDWORD size_in_byte, void* allocatedBuf) {
|
bool CKStateChunk::ReadBuffer(void** ppData, CKDWORD* size_in_byte) {
|
||||||
if (allocatedBuf == nullptr) return false;
|
if (ppData == nullptr || size_in_byte == nullptr) return false;
|
||||||
return this->ReadByteData(allocatedBuf, size_in_byte);
|
*ppData = nullptr;
|
||||||
}
|
*size_in_byte = 0;
|
||||||
|
|
||||||
bool CKStateChunk::ReadBuffer(void** buf, CKDWORD* len_in_byte) {
|
// read size first
|
||||||
if (buf == nullptr || len_in_byte == nullptr) return false;
|
if (!this->ReadStruct(size_in_byte)) {
|
||||||
|
|
||||||
// get buffer size.
|
|
||||||
CKDWORD bufByteSize = 0u;
|
|
||||||
if (!this->ReadStruct(bufByteSize)) {
|
|
||||||
*buf = nullptr;
|
|
||||||
*len_in_byte = 0;
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
*len_in_byte = bufByteSize;
|
|
||||||
|
|
||||||
// special treat for zero length buffer
|
// if it is empty buffer, create a fake buffer
|
||||||
if (bufByteSize == 0) {
|
// and simply return it.
|
||||||
*buf = nullptr;
|
if (*size_in_byte == 0) {
|
||||||
|
*ppData = new CKBYTE[1];
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// create buffer
|
// use LockReadBuffer to get pointer
|
||||||
*buf = new CKBYTE[bufByteSize];
|
auto locker = LockReadBufferWrapper(*size_in_byte);
|
||||||
|
if (locker == nullptr) {
|
||||||
// read data
|
*size_in_byte = 0;
|
||||||
if (!this->ReadByteData(*buf, bufByteSize)) {
|
|
||||||
this->DeleteBuffer(*buf);
|
|
||||||
*buf = nullptr;
|
|
||||||
*len_in_byte = 0;
|
|
||||||
return false;
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKStateChunk::DeleteBuffer(const void* buf) {
|
void CKStateChunk::DeleteBuffer(const void* buf) {
|
||||||
if (buf == nullptr) return;
|
if (buf == nullptr) return;
|
||||||
delete[] reinterpret_cast<const CKBYTE*>(buf);
|
delete[] reinterpret_cast<const CKBYTE*>(buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
CKStateChunk::Buffer_t CKStateChunk::ReadBufferWrapper() {
|
CKStateChunk::Buffer_t CKStateChunk::ReadBufferWrapper() {
|
||||||
void* bufcache = nullptr;
|
void* cache;
|
||||||
CKDWORD len_in_byte;
|
CKDWORD size;
|
||||||
bool ret = ReadBuffer(&bufcache, &len_in_byte);
|
if (!ReadBuffer(&cache, &size)) {
|
||||||
if (ret) {
|
|
||||||
return Buffer_t(bufcache, BufferDeleter(this, len_in_byte));
|
|
||||||
} else {
|
|
||||||
return Buffer_t();
|
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 ==========*/
|
/* ========== Sequence Functions ==========*/
|
||||||
|
|
|
@ -79,14 +79,16 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
// read and set vertex count
|
// read and set vertex count
|
||||||
CKDWORD vertexCount;
|
CKDWORD vertexCount;
|
||||||
chunk->ReadStruct(vertexCount);
|
chunk->ReadStruct(vertexCount);
|
||||||
|
SetVertexCount(vertexCount);
|
||||||
|
|
||||||
if (vertexCount != 0) {
|
if (vertexCount != 0) {
|
||||||
// read save flags
|
// read save flags
|
||||||
chunk->ReadStruct(saveflags);
|
chunk->ReadStruct(saveflags);
|
||||||
|
|
||||||
// read size in dword
|
// read size in dword (including it self)
|
||||||
CKDWORD sizeInDword;
|
CKDWORD sizeInDword;
|
||||||
chunk->ReadStruct(sizeInDword);
|
chunk->ReadStruct(sizeInDword);
|
||||||
|
--sizeInDword; // remove self.
|
||||||
|
|
||||||
// lock read buffer
|
// lock read buffer
|
||||||
auto buf = chunk->LockReadBufferWrapper(sizeInDword * CKSizeof(CKDWORD));
|
auto buf = chunk->LockReadBufferWrapper(sizeInDword * CKSizeof(CKDWORD));
|
||||||
|
@ -211,7 +213,14 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
chunk->ReadStruct(lineCount);
|
chunk->ReadStruct(lineCount);
|
||||||
SetLineCount(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;
|
return true;
|
||||||
|
@ -227,6 +236,10 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
SetLineCount(0);
|
SetLineCount(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CKMesh::BuildNormals() {}
|
||||||
|
|
||||||
|
void CKMesh::BuildFaceNormals() {}
|
||||||
|
|
||||||
#pragma region Vertex Section
|
#pragma region Vertex Section
|
||||||
|
|
||||||
CKDWORD CKMesh::GetVertexCount() {
|
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;
|
if (dst_desc == nullptr) return;
|
||||||
|
|
||||||
CKDWORD* pixels = dst_desc->GetMutablePixels();
|
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.
|
* @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.
|
* @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