#include "dynos.cpp.h" extern "C" { #include "engine/graph_node.h" } #define F32VTX_SENTINEL_0 0x3346 #define F32VTX_SENTINEL_1 0x5632 #define F32VTX_SENTINEL_2 0x5854 static inline bool ShouldUseF32Vtx(DataNode* aNode) { for (u32 i = 0; i != aNode->mSize; ++i) { for (u32 j = 0; j != 3; ++j) { if (aNode->mData[i].n.ob[j] < -0x7FFF || aNode->mData[i].n.ob[j] > +0x7FFF) { return true; } } } return false; } static inline bool IsUsingF32Vtx(Vec3f ob) { return ob[0] == F32VTX_SENTINEL_0 && ob[1] == F32VTX_SENTINEL_1 && ob[2] == F32VTX_SENTINEL_2; } ///////////// // Parsing // ///////////// DataNode* DynOS_Vtx_Parse(GfxData* aGfxData, DataNode* aNode) { if (aNode->mData) return aNode; // Vertex data aNode->mSize = (u32) (aNode->mTokens.Count() / 10); aNode->mData = New(aNode->mSize); for (u32 i = 0; i != aNode->mSize; ++i) { f32 px = (f32) aNode->mTokens[10 * i + 0].ParseFloat(); f32 py = (f32) aNode->mTokens[10 * i + 1].ParseFloat(); f32 pz = (f32) aNode->mTokens[10 * i + 2].ParseFloat(); u8 fl = (u8) aNode->mTokens[10 * i + 3].ParseInt(); s16 tu = (s16) aNode->mTokens[10 * i + 4].ParseInt(); s16 tv = (s16) aNode->mTokens[10 * i + 5].ParseInt(); u8 nx = (u8) aNode->mTokens[10 * i + 6].ParseInt(); u8 ny = (u8) aNode->mTokens[10 * i + 7].ParseInt(); u8 nz = (u8) aNode->mTokens[10 * i + 8].ParseInt(); u8 a = (u8) aNode->mTokens[10 * i + 9].ParseInt(); aNode->mData[i] = { { { px, py, pz }, fl, { tu, tv }, { nx, ny, nz, a } } }; } aNode->mLoadIndex = aGfxData->mLoadIndex++; return aNode; } ///////////// // Writing // ///////////// void DynOS_Vtx_Write(BinFile* aFile, GfxData* aGfxData, DataNode *aNode) { if (!aNode->mData) return; // Header aFile->Write(DATA_TYPE_VERTEX); aNode->mName.Write(aFile); // Data bool shouldUseF32Vtx = ShouldUseF32Vtx(aNode); if (shouldUseF32Vtx) { aFile->Write(aNode->mSize + 1); // Write sentinel aFile->Write(F32VTX_SENTINEL_0); aFile->Write(F32VTX_SENTINEL_1); aFile->Write(F32VTX_SENTINEL_2); aFile->Write(0); aFile->Write(0); aFile->Write(0); aFile->Write (0); aFile->Write (0); aFile->Write (0); aFile->Write (0); } else { aFile->Write(aNode->mSize); } for (u32 i = 0; i != aNode->mSize; ++i) { if (shouldUseF32Vtx) { aFile->Write(aNode->mData[i].n.ob[0]); aFile->Write(aNode->mData[i].n.ob[1]); aFile->Write(aNode->mData[i].n.ob[2]); } else { aFile->Write(aNode->mData[i].n.ob[0]); aFile->Write(aNode->mData[i].n.ob[1]); aFile->Write(aNode->mData[i].n.ob[2]); } aFile->Write(aNode->mData[i].n.flag); aFile->Write(aNode->mData[i].n.tc[0]); aFile->Write(aNode->mData[i].n.tc[1]); aFile->Write (aNode->mData[i].n.n[0]); aFile->Write (aNode->mData[i].n.n[1]); aFile->Write (aNode->mData[i].n.n[2]); aFile->Write (aNode->mData[i].n.a); } } ///////////// // Reading // ///////////// void DynOS_Vtx_Load(BinFile *aFile, GfxData *aGfxData) { DataNode *_Node = New>(); // Name _Node->mName.Read(aFile); // Data bool isUsingF32Vtx = false; _Node->mSize = aFile->Read(); _Node->mData = New(_Node->mSize); for (u32 i = 0; i != _Node->mSize; ++i) { if (isUsingF32Vtx) { _Node->mData[i].n.ob[0] = aFile->Read(); _Node->mData[i].n.ob[1] = aFile->Read(); _Node->mData[i].n.ob[2] = aFile->Read(); } else { _Node->mData[i].n.ob[0] = aFile->Read(); _Node->mData[i].n.ob[1] = aFile->Read(); _Node->mData[i].n.ob[2] = aFile->Read(); } _Node->mData[i].n.flag = aFile->Read(); _Node->mData[i].n.tc[0] = aFile->Read(); _Node->mData[i].n.tc[1] = aFile->Read(); _Node->mData[i].n.n[0] = aFile->Read (); _Node->mData[i].n.n[1] = aFile->Read (); _Node->mData[i].n.n[2] = aFile->Read (); _Node->mData[i].n.a = aFile->Read (); // Check sentinel on first vertex if (!isUsingF32Vtx && i == 0 && IsUsingF32Vtx(_Node->mData[i].n.ob)) { _Node->mSize--; i--; isUsingF32Vtx = true; } } // Append aGfxData->mVertices.Add(_Node); }