From dfb9bbb5f68858321769ce5c976ee89a42e13db5 Mon Sep 17 00:00:00 2001 From: turanszkij Date: Wed, 22 Jun 2016 00:04:03 +0200 Subject: [PATCH] enforced platform agnostic serialization + version barrier --- WickedEngine/wiArchive.cpp | 11 +- WickedEngine/wiArchive.h | 273 ++++++++++++++++++++++++++++++++----- WickedEngine/wiLoader.cpp | 122 +++++++++++++---- WickedEngine/wiLoader.h | 3 + WickedEngine/wiVersion.cpp | 2 +- 5 files changed, 345 insertions(+), 66 deletions(-) diff --git a/WickedEngine/wiArchive.cpp b/WickedEngine/wiArchive.cpp index 26e6bea2d..f7045d2b8 100644 --- a/WickedEngine/wiArchive.cpp +++ b/WickedEngine/wiArchive.cpp @@ -1,7 +1,10 @@ #include "wiArchive.h" +#include "wiHelper.h" // this should always be only INCREMENTED and only if a new serialization is implemeted somewhere! -unsigned long __archiveVersion = 0; +uint64_t __archiveVersion = 1; +// this is the version number of which below the archive is not compatible with the current version +uint64_t __archiveVersionBarrier = 1; wiArchive::wiArchive(const string& fileName, bool readMode):readMode(readMode),pos(0),DATA(nullptr) { @@ -18,6 +21,12 @@ wiArchive::wiArchive(const string& fileName, bool readMode):readMode(readMode),p file.read(DATA, dataSize); file.close(); (*this) >> version; + if (version < __archiveVersionBarrier) + { + stringstream ss(""); + ss << "The archive version (" << version << ") is no longer supported!"; + wiHelper::messageBox(ss.str(), "Error!"); + } } } else diff --git a/WickedEngine/wiArchive.h b/WickedEngine/wiArchive.h index eedce78e2..dcd378286 100644 --- a/WickedEngine/wiArchive.h +++ b/WickedEngine/wiArchive.h @@ -1,10 +1,11 @@ #pragma once #include "CommonInclude.h" +#include class wiArchive { private: - unsigned long version; + uint64_t version; fstream file; bool readMode; streamsize pos; @@ -13,14 +14,122 @@ public: wiArchive(const string& fileName, bool readMode = true); ~wiArchive(); - unsigned long GetVersion() { return version; } + uint64_t GetVersion() { return version; } bool IsReadMode() { return readMode; } bool IsOpen(); void Close(); + // It could be templated but we have to be extremely careful of different datasizes on different platforms + // because serialized data should be interchangeable! + // So providing exact copy operations for exact types enforces platform agnosticism + // Write data using file operations - template - wiArchive& operator<<(const T& data) + wiArchive& operator<<(bool data) + { + uint32_t temp = (uint32_t)(data ? 1 : 0); + file.seekp(pos); + file.write(reinterpret_cast(&temp), sizeof(temp)); + pos += sizeof(temp); + return *this; + } + wiArchive& operator<<(int data) + { + int64_t temp = (int64_t)data; + file.seekp(pos); + file.write(reinterpret_cast(&temp), sizeof(temp)); + pos += sizeof(temp); + return *this; + } + wiArchive& operator<<(unsigned int data) + { + uint64_t temp = (uint64_t)data; + file.seekp(pos); + file.write(reinterpret_cast(&temp), sizeof(temp)); + pos += sizeof(temp); + return *this; + } + wiArchive& operator<<(long data) + { + int64_t temp = (int64_t)data; + file.seekp(pos); + file.write(reinterpret_cast(&temp), sizeof(temp)); + pos += sizeof(temp); + return *this; + } + wiArchive& operator<<(unsigned long data) + { + uint64_t temp = (uint64_t)data; + file.seekp(pos); + file.write(reinterpret_cast(&temp), sizeof(temp)); + pos += sizeof(temp); + return *this; + } + wiArchive& operator<<(long long data) + { + int64_t temp = (int64_t)data; + file.seekp(pos); + file.write(reinterpret_cast(&temp), sizeof(temp)); + pos += sizeof(temp); + return *this; + } + wiArchive& operator<<(unsigned long long data) + { + uint64_t temp = (uint64_t)data; + file.seekp(pos); + file.write(reinterpret_cast(&temp), sizeof(temp)); + pos += sizeof(temp); + return *this; + } + wiArchive& operator<<(float data) + { + file.seekp(pos); + file.write(reinterpret_cast(&data), sizeof(data)); + pos += sizeof(data); + return *this; + } + wiArchive& operator<<(double data) + { + file.seekp(pos); + file.write(reinterpret_cast(&data), sizeof(data)); + pos += sizeof(data); + return *this; + } + wiArchive& operator<<(const XMFLOAT2& data) + { + file.seekp(pos); + file.write(reinterpret_cast(&data), sizeof(data)); + pos += sizeof(data); + return *this; + } + wiArchive& operator<<(const XMFLOAT3& data) + { + file.seekp(pos); + file.write(reinterpret_cast(&data), sizeof(data)); + pos += sizeof(data); + return *this; + } + wiArchive& operator<<(const XMFLOAT4& data) + { + file.seekp(pos); + file.write(reinterpret_cast(&data), sizeof(data)); + pos += sizeof(data); + return *this; + } + wiArchive& operator<<(const XMFLOAT3X3& data) + { + file.seekp(pos); + file.write(reinterpret_cast(&data), sizeof(data)); + pos += sizeof(data); + return *this; + } + wiArchive& operator<<(const XMFLOAT4X3& data) + { + file.seekp(pos); + file.write(reinterpret_cast(&data), sizeof(data)); + pos += sizeof(data); + return *this; + } + wiArchive& operator<<(const XMFLOAT4X4& data) { file.seekp(pos); file.write(reinterpret_cast(&data), sizeof(data)); @@ -30,7 +139,7 @@ public: wiArchive& operator<<(const string& data) { file.seekp(pos); - size_t len = data.length() + 1; // +1 for the null-terminator + uint64_t len = (uint64_t)(data.length() + 1); // +1 for the null-terminator file.write(reinterpret_cast(&len), sizeof(len)); pos += sizeof(len); file.seekp(pos); @@ -40,49 +149,141 @@ public: } // Read data using memory operations - template - wiArchive& operator >> (T& data) + wiArchive& operator >> (bool& data) { - memcpy(&data, reinterpret_cast((int)DATA + (int)pos), sizeof(data)); + uint32_t temp; + memcpy(&temp, reinterpret_cast((uint64_t)DATA + (uint64_t)pos), sizeof(temp)); + pos += sizeof(temp); + data = (temp == 1); + return *this; + } + wiArchive& operator >> (int& data) + { + int64_t temp; + memcpy(&temp, reinterpret_cast((uint64_t)DATA + (uint64_t)pos), sizeof(temp)); + pos += sizeof(temp); + data = (int)temp; + return *this; + } + wiArchive& operator >> (unsigned int& data) + { + uint64_t temp; + memcpy(&temp, reinterpret_cast((uint64_t)DATA + (uint64_t)pos), sizeof(temp)); + pos += sizeof(temp); + data = (unsigned int)temp; + return *this; + } + wiArchive& operator >> (long& data) + { + int64_t temp; + memcpy(&temp, reinterpret_cast((uint64_t)DATA + (uint64_t)pos), sizeof(temp)); + pos += sizeof(temp); + data = (long)temp; + return *this; + } + wiArchive& operator >> (unsigned long& data) + { + uint64_t temp; + memcpy(&temp, reinterpret_cast((uint64_t)DATA + (uint64_t)pos), sizeof(temp)); + pos += sizeof(temp); + data = (unsigned long)temp; + return *this; + } + wiArchive& operator >> (long long& data) + { + int64_t temp; + memcpy(&temp, reinterpret_cast((uint64_t)DATA + (uint64_t)pos), sizeof(temp)); + pos += sizeof(temp); + data = (long long)temp; + return *this; + } + wiArchive& operator >> (unsigned long long& data) + { + uint64_t temp; + memcpy(&temp, reinterpret_cast((uint64_t)DATA + (uint64_t)pos), sizeof(temp)); + pos += sizeof(temp); + data = (unsigned long long)temp; + return *this; + } + wiArchive& operator >> (float& data) + { + memcpy(&data, reinterpret_cast((uint64_t)DATA + (uint64_t)pos), sizeof(data)); + pos += sizeof(data); + return *this; + } + wiArchive& operator >> (double& data) + { + memcpy(&data, reinterpret_cast((uint64_t)DATA + (uint64_t)pos), sizeof(data)); + pos += sizeof(data); + return *this; + } + wiArchive& operator >> (XMFLOAT2& data) + { + memcpy(&data, reinterpret_cast((uint64_t)DATA + (uint64_t)pos), sizeof(data)); + pos += sizeof(data); + return *this; + } + wiArchive& operator >> (XMFLOAT3& data) + { + memcpy(&data, reinterpret_cast((uint64_t)DATA + (uint64_t)pos), sizeof(data)); + pos += sizeof(data); + return *this; + } + wiArchive& operator >> (XMFLOAT4& data) + { + memcpy(&data, reinterpret_cast((uint64_t)DATA + (uint64_t)pos), sizeof(data)); + pos += sizeof(data); + return *this; + } + wiArchive& operator >> (XMFLOAT3X3& data) + { + memcpy(&data, reinterpret_cast((uint64_t)DATA + (uint64_t)pos), sizeof(data)); + pos += sizeof(data); + return *this; + } + wiArchive& operator >> (XMFLOAT4X3& data) + { + memcpy(&data, reinterpret_cast((uint64_t)DATA + (uint64_t)pos), sizeof(data)); + pos += sizeof(data); + return *this; + } + wiArchive& operator >> (XMFLOAT4X4& data) + { + memcpy(&data, reinterpret_cast((uint64_t)DATA + (uint64_t)pos), sizeof(data)); pos += sizeof(data); return *this; } wiArchive& operator >> (string& data) { - size_t len; + uint64_t len; (*this) >> len; - char* str = new char[len]; - memset(str, '\0', sizeof(char)*len); - memcpy(str, reinterpret_cast((int)DATA + (int)pos), sizeof(char)*len); - pos += sizeof(char)*len; + char* str = new char[(size_t)len]; + memset(str, '\0', (size_t)(sizeof(char)*len)); + memcpy(str, reinterpret_cast((uint64_t)DATA + (uint64_t)pos), (size_t)(sizeof(char)*len)); + pos += (size_t)(sizeof(char)*len); data = string(str); delete[] str; return *this; } - //template - //wiArchive& operator >> (T& data) - //{ - // file.seekg(pos); - // file.read(reinterpret_cast(&data), sizeof(data)); - // pos += sizeof(data); - // return *this; - //} - //wiArchive& operator >> (string& data) - //{ - // file.seekg(pos); - // size_t len; - // file.read(reinterpret_cast(&len), sizeof(len)); - // pos += sizeof(len); - // char* str = new char[len]; - // memset(str, '\0', sizeof(char)*len); - // file.seekg(pos); - // file.read(str, sizeof(char)*len); - // pos += sizeof(char)*len; - // data = string(str); - // delete[] str; - // return *this; - //} + +//private: +// +// template +// wiArchive& operator<<(const T& data) +// { +// file.seekp(pos); +// file.write(reinterpret_cast(&data), sizeof(data)); +// pos += sizeof(data); +// return *this; +// } +// template +// wiArchive& operator >> (T& data) +// { +// memcpy(&data, reinterpret_cast((int)DATA + (int)pos), sizeof(data)); +// pos += sizeof(data); +// return *this; +// } }; diff --git a/WickedEngine/wiLoader.cpp b/WickedEngine/wiLoader.cpp index 002c08def..41e2da126 100644 --- a/WickedEngine/wiLoader.cpp +++ b/WickedEngine/wiLoader.cpp @@ -1272,6 +1272,28 @@ void GenerateSPTree(wiSPTree*& tree, vector& objects, int type){ tree->initialize(objects); } +#pragma region SKINNEDVERTEX +void SkinnedVertex::Serialize(wiArchive& archive) +{ + if (archive.IsReadMode()) + { + archive >> pos; + archive >> nor; + archive >> tex; + archive >> bon; + archive >> wei; + } + else + { + archive << pos; + archive << nor; + archive << tex; + archive << bon; + archive << wei; + } +} +#pragma endregion + #pragma region SCENE Scene::Scene() { @@ -1325,14 +1347,7 @@ void Scene::Update() Cullable::Cullable():bounds(AABB())/*,lastSquaredDistMulThousand(0)*/{} void Cullable::Serialize(wiArchive& archive) { - if (archive.IsReadMode()) - { - archive >> bounds; - } - else - { - archive << bounds; - } + bounds.Serialize(archive); } #pragma endregion @@ -1435,7 +1450,9 @@ void Material::Serialize(wiArchive& archive) archive >> refMapName; archive >> textureName; archive >> premultipliedTexture; - archive >> blendFlag; + int temp; + archive >> temp; + blendFlag = (BLENDMODE)temp; archive >> normalMapName; archive >> displacementMapName; archive >> specularMapName; @@ -1481,7 +1498,7 @@ void Material::Serialize(wiArchive& archive) archive << refMapName; archive << textureName; archive << premultipliedTexture; - archive << blendFlag; + archive << (int)blendFlag; archive << normalMapName; archive << displacementMapName; archive << specularMapName; @@ -2001,7 +2018,7 @@ void Mesh::Serialize(wiArchive& archive) SkinnedVertex tempVert; for (size_t i = 0; i < vertexCount; ++i) { - archive >> tempVert; + tempVert.Serialize(archive); vertices.push_back(tempVert); } } @@ -2082,7 +2099,9 @@ void Mesh::Serialize(wiArchive& archive) } archive >> renderable; archive >> doubleSided; - archive >> stencilRef; + int temp; + archive >> temp; + stencilRef = (STENCILREF)temp; archive >> calculatedAO; archive >> trailInfo.base; archive >> trailInfo.tip; @@ -2094,8 +2113,8 @@ void Mesh::Serialize(wiArchive& archive) archive >> massVG; archive >> goalVG; archive >> softVG; - archive >> aabb; archive >> armatureName; + aabb.Serialize(archive); } else { @@ -2107,7 +2126,7 @@ void Mesh::Serialize(wiArchive& archive) archive << vertices.size(); for (auto& x : vertices) { - archive << x; + x.Serialize(archive); } } // indices @@ -2164,7 +2183,7 @@ void Mesh::Serialize(wiArchive& archive) } archive << renderable; archive << doubleSided; - archive << stencilRef; + archive << (int)stencilRef; archive << calculatedAO; archive << trailInfo.base; archive << trailInfo.tip; @@ -2176,8 +2195,8 @@ void Mesh::Serialize(wiArchive& archive) archive << massVG; archive << goalVG; archive << softVG; - archive << aabb; archive << armatureName; + aabb.Serialize(archive); } } #pragma endregion @@ -2735,6 +2754,31 @@ AABB AABB::Merge(const AABB& a, const AABB& b) { return AABB(wiMath::Min(a.getMin(), b.getMin()), wiMath::Max(a.getMax(), b.getMax())); } +void AABB::Serialize(wiArchive& archive) +{ + if (archive.IsReadMode()) + { + archive >> corners[0]; + archive >> corners[1]; + archive >> corners[2]; + archive >> corners[3]; + archive >> corners[4]; + archive >> corners[5]; + archive >> corners[6]; + archive >> corners[7]; + } + else + { + archive << corners[0]; + archive << corners[1]; + archive << corners[2]; + archive << corners[3]; + archive << corners[4]; + archive << corners[5]; + archive << corners[6]; + archive << corners[7]; + } +} #pragma endregion #pragma region SPHERE @@ -2836,19 +2880,19 @@ void Bone::Serialize(wiArchive& archive) archive >> tempCount; for (size_t i = 0; i < tempCount; ++i) { - archive >> tempKeyFrame; + tempKeyFrame.Serialize(archive); aframes.keyframesRot.push_back(tempKeyFrame); } archive >> tempCount; for (size_t i = 0; i < tempCount; ++i) { - archive >> tempKeyFrame; + tempKeyFrame.Serialize(archive); aframes.keyframesPos.push_back(tempKeyFrame); } archive >> tempCount; for (size_t i = 0; i < tempCount; ++i) { - archive >> tempKeyFrame; + tempKeyFrame.Serialize(archive); aframes.keyframesSca.push_back(tempKeyFrame); } actionFrames.push_back(aframes); @@ -2874,17 +2918,17 @@ void Bone::Serialize(wiArchive& archive) archive << x.keyframesRot.size(); for (auto& y : x.keyframesRot) { - archive << y; + y.Serialize(archive); } archive << x.keyframesPos.size(); for (auto& y : x.keyframesPos) { - archive << y; + y.Serialize(archive); } archive << x.keyframesSca.size(); for (auto& y : x.keyframesSca) { - archive << y; + y.Serialize(archive); } } archive << recursivePose; @@ -2896,6 +2940,22 @@ void Bone::Serialize(wiArchive& archive) } #pragma endregion +#pragma region KEYFRAME +void KeyFrame::Serialize(wiArchive& archive) +{ + if (archive.IsReadMode()) + { + archive >> data; + archive >> frameI; + } + else + { + archive << data; + archive << frameI; + } +} +#pragma endregion + #pragma region ANIMATIONLAYER AnimationLayer::AnimationLayer() { @@ -2956,7 +3016,9 @@ void AnimationLayer::Serialize(wiArchive& archive) archive >> blendFrames; archive >> blendFact; archive >> weight; - archive >> type; + int temp; + archive >> temp; + type = (ANIMATIONLAYER_TYPE)temp; archive >> looped; } else @@ -2965,7 +3027,7 @@ void AnimationLayer::Serialize(wiArchive& archive) archive << blendFrames; archive << blendFact; archive << weight; - archive << type; + archive << (int)type; archive << looped; } } @@ -3573,7 +3635,9 @@ void Object::Serialize(wiArchive& archive) if (archive.IsReadMode()) { - archive >> emitterType; + int temp; + archive >> temp; + emitterType = (EmitterType)temp; archive >> transparency; archive >> color; archive >> rigidBody; @@ -3604,7 +3668,7 @@ void Object::Serialize(wiArchive& archive) } else { - archive << emitterType; + archive << (int)emitterType; archive << transparency; archive << color; archive << rigidBody; @@ -3744,7 +3808,9 @@ void Light::Serialize(wiArchive& archive) archive >> noHalo; archive >> shadow; archive >> shadowBias; - archive >> type; + int temp; + archive >> temp; + type = (LightType)temp; if (type == DIRECTIONAL) { shadowMaps_dirLight.resize(3); @@ -3769,7 +3835,7 @@ void Light::Serialize(wiArchive& archive) archive << noHalo; archive << shadow; archive << shadowBias; - archive << type; + archive << (int)type; archive << lensFlareNames.size(); for (auto& x : lensFlareNames) { diff --git a/WickedEngine/wiLoader.h b/WickedEngine/wiLoader.h index 017172972..9bacda749 100644 --- a/WickedEngine/wiLoader.h +++ b/WickedEngine/wiLoader.h @@ -48,6 +48,7 @@ struct SkinnedVertex bon=XMFLOAT4(0,0,0,0); wei=XMFLOAT4(0,0,0,0); } + void Serialize(wiArchive& archive); }; struct Vertex { @@ -272,6 +273,7 @@ struct AABB{ bool intersects(const RAY& ray) const; AABB operator* (float a); static AABB Merge(const AABB& a, const AABB& b); + void Serialize(wiArchive& archive); }; struct SPHERE{ float radius; @@ -520,6 +522,7 @@ struct KeyFrame frameI=newFrameI; data=XMFLOAT4(x,y,z,w); } + void Serialize(wiArchive& archive); }; struct Action { diff --git a/WickedEngine/wiVersion.cpp b/WickedEngine/wiVersion.cpp index 36a514888..d29c1d22e 100644 --- a/WickedEngine/wiVersion.cpp +++ b/WickedEngine/wiVersion.cpp @@ -7,7 +7,7 @@ namespace wiVersion // minor features, major bug fixes const int minor = 8; // minor bug fixes, alterations, refactors - const int revision = 18; + const int revision = 19; long GetVersion()