finish CKMesh remain reading and ctor
This commit is contained in:
parent
0a85832d63
commit
a06f6a58c9
|
@ -312,9 +312,13 @@ namespace LibCmo::CK2 {
|
||||||
/* ========== Complex Data Read Functions ==========*/
|
/* ========== Complex Data Read Functions ==========*/
|
||||||
|
|
||||||
bool ReadObjectID(CK_ID* id);
|
bool ReadObjectID(CK_ID* id);
|
||||||
|
bool ReadObjectPointer(ObjImpls::CKObject** obj);
|
||||||
inline bool ReadObjectID(CK_ID& id) {
|
inline bool ReadObjectID(CK_ID& id) {
|
||||||
return ReadObjectID(&id);
|
return ReadObjectID(&id);
|
||||||
}
|
}
|
||||||
|
inline bool ReadObjectPointer(ObjImpls::CKObject*& id) {
|
||||||
|
return ReadObjectPointer(&id);
|
||||||
|
}
|
||||||
|
|
||||||
bool ReadManagerInt(CKGUID* guid, CKINT* intval);
|
bool ReadManagerInt(CKGUID* guid, CKINT* intval);
|
||||||
inline bool ReadManagerInt(CKGUID& guid, CKINT& intval) {
|
inline bool ReadManagerInt(CKGUID& guid, CKINT& intval) {
|
||||||
|
@ -424,8 +428,8 @@ namespace LibCmo::CK2 {
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="ls"></param>
|
/// <param name="ls"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
bool ReadObjectIDSequence(XContainer::XArray<CK_ID>* ls);
|
bool ReadObjectIDSequence(XContainer::XObjectArray* ls);
|
||||||
inline bool ReadObjectIDSequence(XContainer::XArray<CK_ID>& ls) {
|
inline bool ReadObjectIDSequence(XContainer::XObjectArray& ls) {
|
||||||
return ReadObjectIDSequence(&ls);
|
return ReadObjectIDSequence(&ls);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -183,6 +183,17 @@ namespace LibCmo::CK2 {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CKStateChunk::ReadObjectPointer(ObjImpls::CKObject** obj) {
|
||||||
|
CK_ID cache;
|
||||||
|
bool ret = ReadObjectID(&cache);
|
||||||
|
if (ret) {
|
||||||
|
*obj = m_BindContext->GetObject(cache);
|
||||||
|
} else {
|
||||||
|
*obj = nullptr;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
bool CKStateChunk::ReadManagerInt(CKGUID* guid, CKINT* intval) {
|
bool CKStateChunk::ReadManagerInt(CKGUID* guid, CKINT* intval) {
|
||||||
if (guid == nullptr || intval == nullptr) return false;
|
if (guid == nullptr || intval == nullptr) return false;
|
||||||
|
|
||||||
|
@ -374,7 +385,7 @@ namespace LibCmo::CK2 {
|
||||||
|
|
||||||
/* ========== Sequence Functions ==========*/
|
/* ========== Sequence Functions ==========*/
|
||||||
|
|
||||||
bool CKStateChunk::ReadObjectIDSequence(XContainer::XArray<CK_ID>* ls) {
|
bool CKStateChunk::ReadObjectIDSequence(XContainer::XObjectArray* ls) {
|
||||||
if (ls == nullptr) return false;
|
if (ls == nullptr) return false;
|
||||||
ls->clear();
|
ls->clear();
|
||||||
|
|
||||||
|
|
|
@ -42,11 +42,10 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
m_PotentialMeshes.clear();
|
m_PotentialMeshes.clear();
|
||||||
|
|
||||||
// read current mesh
|
// read current mesh
|
||||||
CK_ID currentMeshId;
|
CKObject* pendingMesh = nullptr;
|
||||||
chunk->ReadObjectID(currentMeshId);
|
chunk->ReadObjectPointer(pendingMesh);
|
||||||
CKObject* findobj = m_Context->GetObject(currentMeshId);
|
if (pendingMesh != nullptr && pendingMesh->GetClassID() == CK_CLASSID::CKCID_MESH) {
|
||||||
if (findobj != nullptr && findobj->GetClassID() == CK_CLASSID::CKCID_MESH) {
|
m_CurrentMesh = static_cast<CKMesh*>(pendingMesh);
|
||||||
m_CurrentMesh = static_cast<CKMesh*>(findobj);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// read other meshs
|
// read other meshs
|
||||||
|
|
|
@ -70,9 +70,8 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
chunk->ReadStruct(m_SpecularPower);
|
chunk->ReadStruct(m_SpecularPower);
|
||||||
|
|
||||||
// main texture
|
// main texture
|
||||||
CK_ID objid;
|
CKObject* tex = nullptr;
|
||||||
chunk->ReadObjectID(objid);
|
chunk->ReadObjectPointer(tex);
|
||||||
CKObject* tex = m_Context->GetObject(objid);
|
|
||||||
if (tex != nullptr && tex->GetClassID() == CK_CLASSID::CKCID_TEXTURE) {
|
if (tex != nullptr && tex->GetClassID() == CK_CLASSID::CKCID_TEXTURE) {
|
||||||
m_Textures[0] = static_cast<CKTexture*>(tex);
|
m_Textures[0] = static_cast<CKTexture*>(tex);
|
||||||
}
|
}
|
||||||
|
@ -125,12 +124,10 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
// extra texture data
|
// extra texture data
|
||||||
if (chunk->SeekIdentifier(CK_STATESAVEFLAGS_MATERIAL::CK_STATESAVE_MATDATA2)) {
|
if (chunk->SeekIdentifier(CK_STATESAVEFLAGS_MATERIAL::CK_STATESAVE_MATDATA2)) {
|
||||||
// read 3 extra texture
|
// read 3 extra texture
|
||||||
CK_ID objid;
|
|
||||||
CKObject* tex = nullptr;
|
CKObject* tex = nullptr;
|
||||||
|
|
||||||
for (size_t i = 1; i < 4; ++i) {
|
for (size_t i = 1; i < 4; ++i) {
|
||||||
chunk->ReadObjectID(objid);
|
chunk->ReadObjectPointer(tex);
|
||||||
tex = m_Context->GetObject(objid);
|
|
||||||
if (tex != nullptr && tex->GetClassID() == CK_CLASSID::CKCID_TEXTURE) {
|
if (tex != nullptr && tex->GetClassID() == CK_CLASSID::CKCID_TEXTURE) {
|
||||||
m_Textures[i] = static_cast<CKTexture*>(tex);
|
m_Textures[i] = static_cast<CKTexture*>(tex);
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,32 @@
|
||||||
namespace LibCmo::CK2::ObjImpls {
|
namespace LibCmo::CK2::ObjImpls {
|
||||||
|
|
||||||
CKMesh::CKMesh(CKContext* ctx, CK_ID ckid, CKSTRING name) :
|
CKMesh::CKMesh(CKContext* ctx, CK_ID ckid, CKSTRING name) :
|
||||||
CKBeObject(ctx, ckid, name) {}
|
CKBeObject(ctx, ckid, name),
|
||||||
|
// init vertex
|
||||||
|
m_VertexCount(0),
|
||||||
|
m_VertexPosition(), m_VertexNormal(), m_VertexUV(),
|
||||||
|
m_VertexColor(), m_VertexSpecularColor(),
|
||||||
|
m_VertexWeight(), m_NoVertexWeight(true),
|
||||||
|
// init mtl slots
|
||||||
|
m_MtlSlotCount(0),
|
||||||
|
m_MaterialSlot(),
|
||||||
|
// init face data
|
||||||
|
m_FaceCount(0),
|
||||||
|
m_FaceIndices(), m_FaceMtlIndex(), m_Faces(),
|
||||||
|
// init line
|
||||||
|
m_LineCount(0),
|
||||||
|
m_LineIndices(),
|
||||||
|
// init mtl channels
|
||||||
|
m_MtlChannelCount(0),
|
||||||
|
m_MaterialChannels(),
|
||||||
|
// init flags
|
||||||
|
m_Flags(EnumsHelper::Merge({
|
||||||
|
VxMath::VXMESH_FLAGS::VXMESH_FORCETRANSPARENCY,
|
||||||
|
VxMath::VXMESH_FLAGS::VXMESH_HASTRANSPARENCY
|
||||||
|
})) {
|
||||||
|
// set visible in default
|
||||||
|
EnumsHelper::Add(m_ObjectFlags, CK_OBJECT_FLAGS::CK_OBJECT_VISIBLE);
|
||||||
|
}
|
||||||
|
|
||||||
CKMesh::~CKMesh() {}
|
CKMesh::~CKMesh() {}
|
||||||
|
|
||||||
|
@ -51,17 +76,15 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
SetMaterialSlotCount(mtlCount);
|
SetMaterialSlotCount(mtlCount);
|
||||||
|
|
||||||
// read slot
|
// read slot
|
||||||
CK_ID mtlId;
|
|
||||||
CKDWORD ph;
|
CKDWORD ph;
|
||||||
CKObject* objptr;
|
CKObject* objptr = nullptr;
|
||||||
for (auto& mtlSlot : m_MaterialSlot) {
|
for (auto& mtlSlot : m_MaterialSlot) {
|
||||||
// read id
|
// read id
|
||||||
chunk->ReadObjectID(mtlId);
|
chunk->ReadObjectPointer(objptr);
|
||||||
// and read a place holder idk what the fuck it is.
|
// and read a place holder idk what the fuck it is.
|
||||||
chunk->ReadStruct(ph);
|
chunk->ReadStruct(ph);
|
||||||
|
|
||||||
// try getting object pointer and assign
|
// try to assign
|
||||||
objptr = m_Context->GetObject(mtlId);
|
|
||||||
if (objptr != nullptr && objptr->GetClassID() == CK_CLASSID::CKCID_MATERIAL) {
|
if (objptr != nullptr && objptr->GetClassID() == CK_CLASSID::CKCID_MATERIAL) {
|
||||||
mtlSlot = static_cast<CKMaterial*>(objptr);
|
mtlSlot = static_cast<CKMaterial*>(objptr);
|
||||||
} else {
|
} else {
|
||||||
|
@ -220,6 +243,99 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
BuildFaceNormals();
|
BuildFaceNormals();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// read material channels
|
||||||
|
if (chunk->SeekIdentifier(CK_STATESAVEFLAGS_MESH::CK_STATESAVE_MESHCHANNELS)) {
|
||||||
|
// read size and resize it
|
||||||
|
CKDWORD chlSize;
|
||||||
|
chunk->ReadStruct(chlSize);
|
||||||
|
SetMtlChannelCount(chlSize);
|
||||||
|
|
||||||
|
for (auto& chl : m_MaterialChannels) {
|
||||||
|
// read material
|
||||||
|
CKObject* mtlobj = nullptr;
|
||||||
|
chunk->ReadObjectPointer(mtlobj);
|
||||||
|
if (mtlobj != nullptr && mtlobj->GetClassID() == CK_CLASSID::CKCID_MATERIAL) {
|
||||||
|
chl.m_Material = static_cast<CKMaterial*>(mtlobj);
|
||||||
|
}
|
||||||
|
|
||||||
|
// read flags and call function to make sure a custom uv can be created if existed.
|
||||||
|
chunk->ReadStruct(chl.m_Flags);
|
||||||
|
SyncVertexCountToMtlChannel();
|
||||||
|
|
||||||
|
// read blend modes
|
||||||
|
chunk->ReadStruct(chl.m_SourceBlend);
|
||||||
|
chunk->ReadStruct(chl.m_DestBlend);
|
||||||
|
|
||||||
|
// read custom vertex
|
||||||
|
CKDWORD uvcount;
|
||||||
|
chunk->ReadStruct(uvcount);
|
||||||
|
if (uvcount != 0) {
|
||||||
|
// make sure no overflow
|
||||||
|
uvcount = std::min(uvcount, chl.m_CustomUV.size());
|
||||||
|
|
||||||
|
CKDWORD bufsize = uvcount * CKSizeof(VxMath::VxVector2);
|
||||||
|
auto locker = chunk->LockReadBufferWrapper(bufsize);
|
||||||
|
std::memcpy(chl.m_CustomUV.data(), locker.get(), bufsize);
|
||||||
|
locker.reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vertex weight
|
||||||
|
CKDWORD weightSize;
|
||||||
|
m_NoVertexWeight = true;
|
||||||
|
if (chunk->SeekIdentifierAndReturnSize(CK_STATESAVEFLAGS_MESH::CK_STATESAVE_MESHWEIGHTS, &weightSize)) {
|
||||||
|
// set it has
|
||||||
|
m_NoVertexWeight = false;
|
||||||
|
// set count
|
||||||
|
CKDWORD weightCount;
|
||||||
|
chunk->ReadStruct(weightCount);
|
||||||
|
|
||||||
|
if (weightSize > CKSizeof(CKFLOAT)) {
|
||||||
|
// a float series
|
||||||
|
// read as a copy, to make sure no memory overflow
|
||||||
|
// because i couldn't understand how original CKMesh operate vertex weight count
|
||||||
|
// seperated with vertex count.
|
||||||
|
auto buf = chunk->ReadBufferWrapper();
|
||||||
|
CKDWORD bufsize = std::min(buf.get_deleter().GetBufferSize(), static_cast<CKDWORD>(m_VertexWeight.size()) * CKSizeof(CKFLOAT));
|
||||||
|
std::memcpy(m_VertexWeight.data(), buf.get(), bufsize);
|
||||||
|
buf.reset();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
// a single float
|
||||||
|
CKFLOAT single;
|
||||||
|
chunk->ReadStruct(single);
|
||||||
|
|
||||||
|
for (auto& weight : m_VertexWeight) {
|
||||||
|
weight = single;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// face mask
|
||||||
|
if (chunk->SeekIdentifier(CK_STATESAVEFLAGS_MESH::CK_STATESAVE_MESHFACECHANMASK)) {
|
||||||
|
// 2 face mask (2 WORD) are compressed into a single DWORD.
|
||||||
|
// and if there is a remained WORD, read it as a single WORD.
|
||||||
|
// according to little endian, the actually stored data is just the mask placed
|
||||||
|
// one by one.
|
||||||
|
// so we just need to allocated it directly
|
||||||
|
|
||||||
|
// read mask count, and limit it to face count
|
||||||
|
CKDWORD maskCount;
|
||||||
|
chunk->ReadStruct(maskCount);
|
||||||
|
maskCount = std::min(maskCount, m_FaceCount);
|
||||||
|
|
||||||
|
auto locker = chunk->LockReadBufferWrapper(maskCount * CKSizeof(CKWORD));
|
||||||
|
const CKWORD* rawptr = static_cast<const CKWORD*>(locker.get());
|
||||||
|
for (auto& f : m_Faces) {
|
||||||
|
f.m_ChannelMask = *rawptr;
|
||||||
|
++rawptr;
|
||||||
|
}
|
||||||
|
locker.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: progressive mesh data is dropper.
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -240,6 +356,8 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
SetMtlChannelCount(0);
|
SetMtlChannelCount(0);
|
||||||
// then clear other
|
// then clear other
|
||||||
SetVertexCount(0);
|
SetVertexCount(0);
|
||||||
|
m_NoVertexWeight = true;
|
||||||
|
|
||||||
SetMaterialSlotCount(0);
|
SetMaterialSlotCount(0);
|
||||||
SetFaceCount(0);
|
SetFaceCount(0);
|
||||||
SetLineCount(0);
|
SetLineCount(0);
|
||||||
|
@ -406,12 +524,16 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKMesh::SetMtlChannelCount(CKDWORD count) {
|
void CKMesh::SetMtlChannelCount(CKDWORD count) {
|
||||||
|
// backup old count
|
||||||
|
CKDWORD oldcount = m_MtlChannelCount;
|
||||||
|
|
||||||
|
// set and resize
|
||||||
m_MtlChannelCount = count;
|
m_MtlChannelCount = count;
|
||||||
m_MaterialChannels.resize(count);
|
m_MaterialChannels.resize(count);
|
||||||
|
|
||||||
// sync mask to each face.
|
// sync mask to each face.
|
||||||
// each face accept all mask in default
|
// each face accept all mask in default
|
||||||
SyncMtlChannelToFaceMask();
|
SyncMtlChannelToFaceMask(oldcount, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
CKMaterial** CKMesh::GetMtlChannelMaterials(CKDWORD& stride) {
|
CKMaterial** CKMesh::GetMtlChannelMaterials(CKDWORD& stride) {
|
||||||
|
@ -457,8 +579,20 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CKMesh::SyncMtlChannelToFaceMask() {
|
void CKMesh::SyncMtlChannelToFaceMask(CKDWORD oldsize, CKDWORD newsize) {
|
||||||
CKWORD mask = static_cast<CKWORD>(~(0xFFFF << m_MtlChannelCount));
|
// use oldsize and newsize to build mask
|
||||||
|
if (oldsize == newsize) return;
|
||||||
|
|
||||||
|
CKWORD mask = 0xFFFF;
|
||||||
|
if (oldsize > newsize) {
|
||||||
|
// channels shrinks
|
||||||
|
// set already removed bits to 1
|
||||||
|
mask = static_cast<CKWORD>(~(0xFFFF << newsize));
|
||||||
|
} else {
|
||||||
|
// channels expand
|
||||||
|
// set new added bits to 1
|
||||||
|
mask = static_cast<CKWORD>(~(0xFFFF << oldsize));
|
||||||
|
}
|
||||||
for (auto& face : m_Faces) {
|
for (auto& face : m_Faces) {
|
||||||
face.m_ChannelMask |= mask;
|
face.m_ChannelMask |= mask;
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
void BuildNormals();
|
void BuildNormals();
|
||||||
void BuildFaceNormals();
|
void BuildFaceNormals();
|
||||||
|
|
||||||
// ===== Line Section =====
|
// ===== Vertex Section =====
|
||||||
public:
|
public:
|
||||||
CKDWORD GetVertexCount();
|
CKDWORD GetVertexCount();
|
||||||
void SetVertexCount(CKDWORD count);
|
void SetVertexCount(CKDWORD count);
|
||||||
|
@ -76,7 +76,7 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
protected:
|
protected:
|
||||||
// 2 sync functions served for material channels.
|
// 2 sync functions served for material channels.
|
||||||
void SyncVertexCountToMtlChannel(); // setup material channel custom uv properly
|
void SyncVertexCountToMtlChannel(); // setup material channel custom uv properly
|
||||||
void SyncMtlChannelToFaceMask(); // request all face accept all material channels.
|
void SyncMtlChannelToFaceMask(CKDWORD oldsize, CKDWORD newsize); // request all face accept all material channels.
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum class VertexSaveFlags : CKDWORD {
|
enum class VertexSaveFlags : CKDWORD {
|
||||||
|
@ -123,6 +123,7 @@ namespace LibCmo::CK2::ObjImpls {
|
||||||
XContainer::XArray<CKDWORD> m_VertexColor;
|
XContainer::XArray<CKDWORD> m_VertexColor;
|
||||||
XContainer::XArray<CKDWORD> m_VertexSpecularColor;
|
XContainer::XArray<CKDWORD> m_VertexSpecularColor;
|
||||||
XContainer::XArray<CKFLOAT> m_VertexWeight;
|
XContainer::XArray<CKFLOAT> m_VertexWeight;
|
||||||
|
bool m_NoVertexWeight; // true if there is actually no vertex weight
|
||||||
|
|
||||||
XContainer::XArray<CKMaterial*> m_MaterialSlot;
|
XContainer::XArray<CKMaterial*> m_MaterialSlot;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user