Remove deprecated asset data upgrades and old model vertex structures
This commit is contained in:
@@ -8,6 +8,9 @@
|
||||
#include "Engine/Content/Factories/BinaryAssetFactory.h"
|
||||
#include "Engine/Serialization/MemoryReadStream.h"
|
||||
#include "Engine/Threading/Threading.h"
|
||||
#if USE_EDITOR
|
||||
#include "Engine/Serialization/MemoryWriteStream.h"
|
||||
#endif
|
||||
|
||||
REGISTER_BINARY_ASSET_WITH_UPGRADER(MaterialInstance, "FlaxEngine.MaterialInstance", MaterialInstanceUpgrader, true);
|
||||
|
||||
|
||||
@@ -23,6 +23,9 @@
|
||||
#include "Engine/Renderer/DrawCall.h"
|
||||
#include "Engine/Threading/Threading.h"
|
||||
#include "Engine/Tools/ModelTool/ModelTool.h"
|
||||
#if USE_EDITOR
|
||||
#include "Engine/Serialization/MemoryWriteStream.h"
|
||||
#endif
|
||||
|
||||
REGISTER_BINARY_ASSET_ABSTRACT(ModelBase, "FlaxEngine.ModelBase");
|
||||
|
||||
@@ -456,6 +459,7 @@ bool Model::Save(bool withMeshDataFromGpu, const StringView& path)
|
||||
return true;
|
||||
}
|
||||
|
||||
// #MODEL_DATA_FORMAT_USAGE
|
||||
meshesStream.WriteUint32(vertices);
|
||||
meshesStream.WriteUint32(triangles);
|
||||
|
||||
|
||||
@@ -19,6 +19,9 @@
|
||||
#include "Engine/Graphics/Models/MeshDeformation.h"
|
||||
#include "Engine/Profiler/ProfilerCPU.h"
|
||||
#include "Engine/Renderer/DrawCall.h"
|
||||
#if USE_EDITOR
|
||||
#include "Engine/Serialization/MemoryWriteStream.h"
|
||||
#endif
|
||||
|
||||
REGISTER_BINARY_ASSET_WITH_UPGRADER(SkinnedModel, "FlaxEngine.SkinnedModel", SkinnedModelAssetUpgrader, true);
|
||||
|
||||
|
||||
@@ -5,9 +5,6 @@
|
||||
#if USE_EDITOR
|
||||
|
||||
#include "BinaryAssetUpgrader.h"
|
||||
#include "Engine/Audio/AudioClip.h"
|
||||
#include "Engine/Tools/AudioTool/OggVorbisDecoder.h"
|
||||
#include "Engine/Serialization/MemoryReadStream.h"
|
||||
|
||||
/// <summary>
|
||||
/// Audio Clip asset upgrader.
|
||||
@@ -23,112 +20,12 @@ public:
|
||||
{
|
||||
static const Upgrader upgraders[] =
|
||||
{
|
||||
{ 1, 2, &Upgrade_1_To_2 },
|
||||
{},
|
||||
};
|
||||
setup(upgraders, ARRAY_COUNT(upgraders));
|
||||
}
|
||||
|
||||
private:
|
||||
// ============================================
|
||||
// Version 1:
|
||||
// Designed: 26.02.2018
|
||||
// Header version 1.
|
||||
// Chunks with audio data.
|
||||
// ============================================
|
||||
// Version 2:
|
||||
// Designed: 08.08.2019
|
||||
// Header version 2.
|
||||
// Chunks with audio data.
|
||||
// ============================================
|
||||
|
||||
/// <summary>
|
||||
/// Audio Clip resource header structure, version 1. Added on 26.02.2018.
|
||||
/// [Deprecated on 08/08/2019, expires on 08/09/2020]
|
||||
/// </summary>
|
||||
struct Header1
|
||||
{
|
||||
AudioFormat Format;
|
||||
AudioDataInfo Info;
|
||||
bool Is3D;
|
||||
bool Streamable;
|
||||
uint32 OriginalSize;
|
||||
uint32 ImportedSize;
|
||||
};
|
||||
|
||||
typedef AudioClip::Header Header2;
|
||||
|
||||
static bool Upgrade_1_To_2(AssetMigrationContext& context)
|
||||
{
|
||||
ASSERT(context.Input.SerializedVersion == 1 && context.Output.SerializedVersion == 2);
|
||||
|
||||
// Copy all chunks
|
||||
if (CopyChunks(context))
|
||||
return true;
|
||||
|
||||
// Convert header
|
||||
if (context.Input.CustomData.IsInvalid())
|
||||
return true;
|
||||
auto& oldHeader = *(Header1*)context.Input.CustomData.Get();
|
||||
Header2 newHeader;
|
||||
newHeader.Format = oldHeader.Format;
|
||||
newHeader.Info = oldHeader.Info;
|
||||
newHeader.Is3D = oldHeader.Is3D;
|
||||
newHeader.Streamable = oldHeader.Streamable;
|
||||
newHeader.OriginalSize = oldHeader.OriginalSize;
|
||||
newHeader.ImportedSize = oldHeader.ImportedSize;
|
||||
Platform::MemoryClear(newHeader.SamplesPerChunk, sizeof(newHeader.SamplesPerChunk));
|
||||
for (int32 chunkIndex = 0; chunkIndex < ASSET_FILE_DATA_CHUNKS; chunkIndex++)
|
||||
{
|
||||
const auto chunk = context.Output.Header.Chunks[chunkIndex];
|
||||
if (!chunk)
|
||||
continue;
|
||||
|
||||
int32 numSamples;
|
||||
switch (oldHeader.Format)
|
||||
{
|
||||
case AudioFormat::Raw:
|
||||
{
|
||||
numSamples = chunk->Size() / (oldHeader.Info.BitDepth / 8);
|
||||
break;
|
||||
}
|
||||
case AudioFormat::Vorbis:
|
||||
{
|
||||
#if COMPILE_WITH_OGG_VORBIS
|
||||
OggVorbisDecoder decoder;
|
||||
MemoryReadStream stream(chunk->Get(), chunk->Size());
|
||||
AudioDataInfo outInfo;
|
||||
if (!decoder.Open(&stream, outInfo, 0))
|
||||
{
|
||||
LOG(Warning, "Audio data open failed (OggVorbisDecoder).");
|
||||
return true;
|
||||
}
|
||||
numSamples = outInfo.NumSamples;
|
||||
#else
|
||||
LOG(Warning, "OggVorbisDecoder is disabled.");
|
||||
return true;
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
default:
|
||||
LOG(Warning, "Unknown audio data format.");
|
||||
return true;
|
||||
}
|
||||
newHeader.SamplesPerChunk[chunkIndex] = numSamples;
|
||||
}
|
||||
context.Output.CustomData.Copy(&newHeader);
|
||||
|
||||
// Validate total amount of samples calculated from the asset chunks
|
||||
uint32 totalSamplesInChunks = 0;
|
||||
for (int32 chunkIndex = 0; chunkIndex < ASSET_FILE_DATA_CHUNKS; chunkIndex++)
|
||||
totalSamplesInChunks += newHeader.SamplesPerChunk[chunkIndex];
|
||||
if (totalSamplesInChunks != newHeader.Info.NumSamples)
|
||||
{
|
||||
LOG(Warning, "Invalid amount of audio data samples in data chunks {0}, audio clip has: {1}.", totalSamplesInChunks, newHeader.Info.NumSamples);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
#if USE_EDITOR
|
||||
|
||||
#include "BinaryAssetUpgrader.h"
|
||||
#include "Engine/Render2D/FontAsset.h"
|
||||
|
||||
/// <summary>
|
||||
/// Font Asset Upgrader
|
||||
@@ -21,55 +20,10 @@ public:
|
||||
{
|
||||
static const Upgrader upgraders[] =
|
||||
{
|
||||
{ 1, 2, &Upgrade_1_To_2 },
|
||||
{ 2, 3, &Upgrade_2_To_3 },
|
||||
{},
|
||||
};
|
||||
setup(upgraders, ARRAY_COUNT(upgraders));
|
||||
}
|
||||
|
||||
private:
|
||||
// ============================================
|
||||
// Version 1:
|
||||
// Designed: long time ago in a galaxy far far away
|
||||
// Custom Data: not used
|
||||
// Chunk 0: Header
|
||||
// Chunk 1: Font File data
|
||||
// ============================================
|
||||
// Version 2:
|
||||
// Designed: 4/20/2017
|
||||
// Custom Data: not used
|
||||
// Chunk 0: Font File data
|
||||
// ============================================
|
||||
// Version 3:
|
||||
// Designed: 10/24/2019
|
||||
// Custom Data: Header1
|
||||
// Chunk 0: Font File data
|
||||
// ============================================
|
||||
|
||||
typedef FontOptions Header1;
|
||||
|
||||
static bool Upgrade_1_To_2(AssetMigrationContext& context)
|
||||
{
|
||||
ASSERT(context.Input.SerializedVersion == 1 && context.Output.SerializedVersion == 2);
|
||||
|
||||
if (context.AllocateChunk(0))
|
||||
return true;
|
||||
context.Output.Header.Chunks[0]->Data.Copy(context.Input.Header.Chunks[1]->Data);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Upgrade_2_To_3(AssetMigrationContext& context)
|
||||
{
|
||||
ASSERT(context.Input.SerializedVersion == 2 && context.Output.SerializedVersion == 3);
|
||||
|
||||
Header1 header;
|
||||
header.Hinting = FontHinting::Default;
|
||||
header.Flags = FontFlags::AntiAliasing;
|
||||
context.Output.CustomData.Copy(&header);
|
||||
|
||||
return CopyChunk(context, 0);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,10 +5,6 @@
|
||||
#if USE_EDITOR
|
||||
|
||||
#include "BinaryAssetUpgrader.h"
|
||||
#include "Engine/Core/Core.h"
|
||||
#include "Engine/Platform/Platform.h"
|
||||
#include "Engine/Serialization/MemoryReadStream.h"
|
||||
#include "Engine/Serialization/MemoryWriteStream.h"
|
||||
|
||||
/// <summary>
|
||||
/// Material Instance Upgrader
|
||||
@@ -24,86 +20,10 @@ public:
|
||||
{
|
||||
static const Upgrader upgraders[] =
|
||||
{
|
||||
{ 1, 3, &Upgrade_1_To_3 },
|
||||
{ 3, 4, &Upgrade_3_To_4 },
|
||||
{},
|
||||
};
|
||||
setup(upgraders, ARRAY_COUNT(upgraders));
|
||||
}
|
||||
|
||||
private:
|
||||
// ============================================
|
||||
// Version 4:
|
||||
// Designed: 5/18/2017
|
||||
// Custom Data: not used
|
||||
// Chunk 0:
|
||||
// - Parent material: Guid
|
||||
// - Material Params
|
||||
// ============================================
|
||||
// Version 3:
|
||||
// Designed: 1/24/2016
|
||||
// Custom Data: not used
|
||||
// Chunk 0:
|
||||
// - Magic Code: int32 ('MI\0@', 1073760589)
|
||||
// - Version: int32
|
||||
// - Parent material: Guid
|
||||
// - Material Params
|
||||
// - Ending char: 1 byte (~)
|
||||
// ============================================
|
||||
|
||||
static bool Upgrade_1_To_3(AssetMigrationContext& context)
|
||||
{
|
||||
ASSERT(context.Input.SerializedVersion == 1 && context.Output.SerializedVersion == 3);
|
||||
|
||||
auto chunk = context.Input.Header.Chunks[0];
|
||||
if (chunk == nullptr || chunk->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing material instance data chunk.");
|
||||
return true;
|
||||
}
|
||||
if (context.AllocateChunk(0))
|
||||
return true;
|
||||
context.Output.Header.Chunks[0]->Data.Copy(chunk->Data);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Upgrade_3_To_4(AssetMigrationContext& context)
|
||||
{
|
||||
ASSERT(context.Input.SerializedVersion == 3 && context.Output.SerializedVersion == 4);
|
||||
|
||||
auto chunk = context.Input.Header.Chunks[0];
|
||||
if (chunk == nullptr || chunk->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing material instance data chunk.");
|
||||
return true;
|
||||
}
|
||||
if (context.AllocateChunk(0))
|
||||
return true;
|
||||
MemoryReadStream inStream(chunk->Data.Get(), chunk->Data.Length());
|
||||
MemoryWriteStream outStream(chunk->Size());
|
||||
|
||||
// Header
|
||||
int32 magicCode;
|
||||
inStream.ReadInt32(&magicCode);
|
||||
int32 version;
|
||||
inStream.ReadInt32(&version);
|
||||
if (magicCode != 1073760589 || version != 3)
|
||||
{
|
||||
LOG(Warning, "Invalid material instance header.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Parent material + Params
|
||||
// TODO: add tool function to copy stream -> stream
|
||||
while (inStream.CanRead())
|
||||
{
|
||||
byte b = inStream.ReadByte();
|
||||
outStream.WriteByte(b);
|
||||
}
|
||||
context.Output.Header.Chunks[0]->Data.Copy(outStream.GetHandle(), outStream.GetPosition());
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -5,8 +5,6 @@
|
||||
#if USE_EDITOR
|
||||
|
||||
#include "BinaryAssetUpgrader.h"
|
||||
#include "Engine/Platform/Platform.h"
|
||||
#include "Engine/Graphics/Shaders/Cache/ShaderStorage.h"
|
||||
|
||||
/// <summary>
|
||||
/// Material Asset and Shader Asset Upgrader
|
||||
@@ -22,96 +20,10 @@ public:
|
||||
{
|
||||
static const Upgrader upgraders[] =
|
||||
{
|
||||
{ 18, 19, &Upgrade_18_To_19 },
|
||||
{ 19, 20, &Upgrade_19_To_20 },
|
||||
{},
|
||||
};
|
||||
setup(upgraders, ARRAY_COUNT(upgraders));
|
||||
}
|
||||
|
||||
private:
|
||||
// ============================================
|
||||
// Versions 18,19,20:
|
||||
// Designed: 7/24/2019
|
||||
// Custom Data: Header
|
||||
// Chunk 0: Material Params
|
||||
// Chunk 1: Internal SM5 cache
|
||||
// Chunk 2: Internal SM4 cache
|
||||
// Chunk 14: Visject Surface data
|
||||
// Chunk 15: Source code: ANSI text (encrypted)
|
||||
// ============================================
|
||||
|
||||
typedef ShaderStorage::Header Header;
|
||||
typedef ShaderStorage::Header20 Header20;
|
||||
typedef ShaderStorage::Header19 Header19;
|
||||
typedef ShaderStorage::Header18 Header18;
|
||||
|
||||
static bool Upgrade_19_To_20(AssetMigrationContext& context)
|
||||
{
|
||||
ASSERT(context.Input.SerializedVersion == 19 && context.Output.SerializedVersion == 20);
|
||||
|
||||
// Convert header
|
||||
if (context.Input.CustomData.IsInvalid())
|
||||
return true;
|
||||
auto& oldHeader = *(Header19*)context.Input.CustomData.Get();
|
||||
Header20 newHeader;
|
||||
Platform::MemoryClear(&newHeader, sizeof(newHeader));
|
||||
if (context.Input.Header.TypeName == TEXT("FlaxEngine.ParticleEmitter"))
|
||||
{
|
||||
newHeader.ParticleEmitter.GraphVersion = oldHeader.ParticleEmitter.GraphVersion;
|
||||
newHeader.ParticleEmitter.CustomDataSize = oldHeader.ParticleEmitter.CustomDataSize;
|
||||
}
|
||||
else if (context.Input.Header.TypeName == TEXT("FlaxEngine.Material"))
|
||||
{
|
||||
newHeader.Material.GraphVersion = oldHeader.Material.GraphVersion;
|
||||
newHeader.Material.Info = oldHeader.Material.Info;
|
||||
}
|
||||
else if (context.Input.Header.TypeName == TEXT("FlaxEngine.Shader"))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(Warning, "Unknown input asset type.");
|
||||
return true;
|
||||
}
|
||||
context.Output.CustomData.Copy(&newHeader);
|
||||
|
||||
// Copy all chunks
|
||||
return CopyChunks(context);
|
||||
}
|
||||
|
||||
static bool Upgrade_18_To_19(AssetMigrationContext& context)
|
||||
{
|
||||
ASSERT(context.Input.SerializedVersion == 18 && context.Output.SerializedVersion == 19);
|
||||
|
||||
// Convert header
|
||||
if (context.Input.CustomData.IsInvalid())
|
||||
return true;
|
||||
auto& oldHeader = *(Header18*)context.Input.CustomData.Get();
|
||||
Header19 newHeader;
|
||||
Platform::MemoryClear(&newHeader, sizeof(newHeader));
|
||||
if (context.Input.Header.TypeName == TEXT("FlaxEngine.ParticleEmitter"))
|
||||
{
|
||||
newHeader.ParticleEmitter.GraphVersion = oldHeader.MaterialVersion;
|
||||
newHeader.ParticleEmitter.CustomDataSize = oldHeader.MaterialInfo.MaxTessellationFactor;
|
||||
}
|
||||
else if (context.Input.Header.TypeName == TEXT("FlaxEngine.Material"))
|
||||
{
|
||||
newHeader.Material.GraphVersion = oldHeader.MaterialVersion;
|
||||
newHeader.Material.Info = oldHeader.MaterialInfo;
|
||||
}
|
||||
else if (context.Input.Header.TypeName == TEXT("FlaxEngine.Shader"))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
LOG(Warning, "Unknown input asset type.");
|
||||
return true;
|
||||
}
|
||||
context.Output.CustomData.Copy(&newHeader);
|
||||
|
||||
// Copy all chunks
|
||||
return CopyChunks(context);
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,10 +5,6 @@
|
||||
#if USE_EDITOR
|
||||
|
||||
#include "BinaryAssetUpgrader.h"
|
||||
#include "Engine/Content/Assets/SkinnedModel.h"
|
||||
#include "Engine/Serialization/MemoryReadStream.h"
|
||||
#include "Engine/Serialization/MemoryWriteStream.h"
|
||||
#include "Engine/Threading/Threading.h"
|
||||
|
||||
/// <summary>
|
||||
/// Skeleton Mask asset upgrader.
|
||||
@@ -24,79 +20,10 @@ public:
|
||||
{
|
||||
static const Upgrader upgraders[] =
|
||||
{
|
||||
{ 1, 2, &Upgrade_1_To_2 },
|
||||
{},
|
||||
};
|
||||
setup(upgraders, ARRAY_COUNT(upgraders));
|
||||
}
|
||||
|
||||
private:
|
||||
static bool Upgrade_1_To_2(AssetMigrationContext& context)
|
||||
{
|
||||
ASSERT(context.Input.SerializedVersion == 1 && context.Output.SerializedVersion == 2);
|
||||
|
||||
// Load data
|
||||
AssetReference<SkinnedModel> skeleton;
|
||||
Array<bool> bonesMask;
|
||||
{
|
||||
auto dataChunk = context.Input.Header.Chunks[0];
|
||||
if (dataChunk == nullptr || dataChunk->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing data chunk.");
|
||||
return true;
|
||||
}
|
||||
MemoryReadStream stream(dataChunk->Get(), dataChunk->Size());
|
||||
|
||||
Guid skeletonId;
|
||||
stream.Read(skeletonId);
|
||||
int32 maskCount;
|
||||
stream.ReadInt32(&maskCount);
|
||||
bonesMask.Resize(maskCount, false);
|
||||
if (maskCount > 0)
|
||||
stream.ReadBytes(bonesMask.Get(), maskCount * sizeof(bool));
|
||||
|
||||
skeleton = skeletonId;
|
||||
if (skeleton && skeleton->WaitForLoaded())
|
||||
{
|
||||
LOG(Warning, "Failed to load skeleton to update skeleton mask.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Build nodes mask from bones
|
||||
Array<String> nodesMask;
|
||||
if (skeleton)
|
||||
{
|
||||
ScopeLock lock(skeleton->Locker);
|
||||
|
||||
for (int32 i = 0; i < bonesMask.Count(); i++)
|
||||
{
|
||||
if (bonesMask[i])
|
||||
{
|
||||
int32 nodeIndex = skeleton->Skeleton.Bones[i].NodeIndex;
|
||||
nodesMask.Add(skeleton->Skeleton.Nodes[nodeIndex].Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save data
|
||||
{
|
||||
if (context.AllocateChunk(0))
|
||||
return true;
|
||||
MemoryWriteStream stream(4096);
|
||||
|
||||
const Guid skeletonId = skeleton.GetID();
|
||||
stream.Write(skeletonId);
|
||||
stream.WriteInt32(nodesMask.Count());
|
||||
for (auto& e : nodesMask)
|
||||
{
|
||||
stream.WriteString(e, -13);
|
||||
}
|
||||
|
||||
context.Output.Header.Chunks[0]->Data.Copy(stream.GetHandle(), stream.GetPosition());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,14 +5,6 @@
|
||||
#if USE_EDITOR
|
||||
|
||||
#include "BinaryAssetUpgrader.h"
|
||||
#include "Engine/Platform/Platform.h"
|
||||
#include "Engine/Serialization/MemoryReadStream.h"
|
||||
#include "Engine/Serialization/MemoryWriteStream.h"
|
||||
#include "Engine/Graphics/Models/Types.h"
|
||||
#include "Engine/Core/Math/BoundingBox.h"
|
||||
#include "Engine/Core/Math/BoundingSphere.h"
|
||||
#include "Engine/Core/Math/Matrix.h"
|
||||
#include "Engine/Core/Math/Transform.h"
|
||||
|
||||
/// <summary>
|
||||
/// Skinned Model Asset Upgrader
|
||||
@@ -28,635 +20,10 @@ public:
|
||||
{
|
||||
static const Upgrader upgraders[] =
|
||||
{
|
||||
{ 1, 2, &Upgrade_1_To_2 }, // [Deprecated on 28.04.2023, expires on 01.01.2024]
|
||||
{ 2, 3, &Upgrade_2_To_3 }, // [Deprecated on 28.04.2023, expires on 01.01.2024]
|
||||
{ 3, 4, &Upgrade_3_To_4 }, // [Deprecated on 28.04.2023, expires on 01.01.2024]
|
||||
{ 4, 5, &Upgrade_4_To_5 }, // [Deprecated on 28.04.2023, expires on 28.04.2026]
|
||||
{},
|
||||
};
|
||||
setup(upgraders, ARRAY_COUNT(upgraders));
|
||||
}
|
||||
|
||||
private:
|
||||
static bool Upgrade_1_To_2(AssetMigrationContext& context)
|
||||
{
|
||||
ASSERT(context.Input.SerializedVersion == 1 && context.Output.SerializedVersion == 2);
|
||||
|
||||
// Copy header chunk (header format is the same)
|
||||
if (CopyChunk(context, 0))
|
||||
return true;
|
||||
|
||||
// Get mesh data chunk
|
||||
const auto srcData = context.Input.Header.Chunks[1];
|
||||
if (srcData == nullptr || srcData->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing model data chunk");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Upgrade meshes data
|
||||
MemoryReadStream stream(srcData->Get(), srcData->Size());
|
||||
MemoryWriteStream output(srcData->Size());
|
||||
do
|
||||
{
|
||||
uint32 vertices;
|
||||
stream.ReadUint32(&vertices);
|
||||
uint32 triangles;
|
||||
stream.ReadUint32(&triangles);
|
||||
const uint32 indicesCount = triangles * 3;
|
||||
const bool use16BitIndexBuffer = indicesCount <= MAX_uint16;
|
||||
const uint32 ibStride = use16BitIndexBuffer ? sizeof(uint16) : sizeof(uint32);
|
||||
if (vertices == 0 || triangles == 0)
|
||||
return true;
|
||||
const auto vb0 = stream.Move<VB0SkinnedElementType1>(vertices);
|
||||
const auto ib = stream.Move<byte>(indicesCount * ibStride);
|
||||
|
||||
// Write back
|
||||
output.WriteUint32(vertices);
|
||||
output.WriteUint32(triangles);
|
||||
for (uint32 i = 0; i < vertices; i++)
|
||||
{
|
||||
const VB0SkinnedElementType1 oldVertex = vb0[i];
|
||||
VB0SkinnedElementType2 newVertex;
|
||||
newVertex.Position = oldVertex.Position;
|
||||
newVertex.TexCoord = oldVertex.TexCoord;
|
||||
newVertex.Normal = oldVertex.Normal;
|
||||
newVertex.Tangent = oldVertex.Tangent;
|
||||
newVertex.BlendIndices = oldVertex.BlendIndices;
|
||||
Float4 blendWeights(oldVertex.BlendWeights.R / 255.0f, oldVertex.BlendWeights.G / 255.0f, oldVertex.BlendWeights.B / 255.0f, oldVertex.BlendWeights.A / 255.0f);
|
||||
const float sum = blendWeights.SumValues();
|
||||
const float invSum = sum > ZeroTolerance ? 1.0f / sum : 0.0f;
|
||||
blendWeights *= invSum;
|
||||
newVertex.BlendWeights = Half4(blendWeights);
|
||||
output.WriteBytes(&newVertex, sizeof(newVertex));
|
||||
}
|
||||
output.WriteBytes(ib, indicesCount * ibStride);
|
||||
} while (stream.CanRead());
|
||||
|
||||
// Save new data
|
||||
if (context.AllocateChunk(1))
|
||||
return true;
|
||||
context.Output.Header.Chunks[1]->Data.Copy(output.GetHandle(), output.GetPosition());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Upgrade_2_To_3(AssetMigrationContext& context)
|
||||
{
|
||||
ASSERT(context.Input.SerializedVersion == 2 && context.Output.SerializedVersion == 3);
|
||||
|
||||
// Copy meshes data chunk (format is the same)
|
||||
if (CopyChunk(context, 1))
|
||||
return true;
|
||||
|
||||
// Rewrite header chunk (added LOD count)
|
||||
const auto srcData = context.Input.Header.Chunks[0];
|
||||
if (srcData == nullptr || srcData->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing model header chunk");
|
||||
return true;
|
||||
}
|
||||
MemoryReadStream stream(srcData->Get(), srcData->Size());
|
||||
MemoryWriteStream output(srcData->Size());
|
||||
{
|
||||
// Min Screen Size
|
||||
float minScreenSize;
|
||||
stream.ReadFloat(&minScreenSize);
|
||||
output.WriteFloat(minScreenSize);
|
||||
|
||||
// Amount of material slots
|
||||
int32 materialSlotsCount;
|
||||
stream.ReadInt32(&materialSlotsCount);
|
||||
output.WriteInt32(materialSlotsCount);
|
||||
|
||||
// For each material slot
|
||||
for (int32 materialSlotIndex = 0; materialSlotIndex < materialSlotsCount; materialSlotIndex++)
|
||||
{
|
||||
// Material
|
||||
Guid materialId;
|
||||
stream.Read(materialId);
|
||||
output.Write(materialId);
|
||||
|
||||
// Shadows Mode
|
||||
output.WriteByte(stream.ReadByte());
|
||||
|
||||
// Name
|
||||
String name;
|
||||
stream.ReadString(&name, 11);
|
||||
output.WriteString(name, 11);
|
||||
}
|
||||
|
||||
// Amount of LODs
|
||||
output.WriteByte(1);
|
||||
|
||||
// Screen Size
|
||||
output.WriteFloat(1.0f);
|
||||
|
||||
// Amount of meshes
|
||||
uint16 meshesCount;
|
||||
stream.ReadUint16(&meshesCount);
|
||||
output.WriteUint16(meshesCount);
|
||||
|
||||
// For each mesh
|
||||
for (uint16 meshIndex = 0; meshIndex < meshesCount; meshIndex++)
|
||||
{
|
||||
// Material Slot index
|
||||
int32 materialSlotIndex;
|
||||
stream.ReadInt32(&materialSlotIndex);
|
||||
output.WriteInt32(materialSlotIndex);
|
||||
|
||||
// Box
|
||||
BoundingBox box;
|
||||
stream.Read(box);
|
||||
output.Write(box);
|
||||
|
||||
// Sphere
|
||||
BoundingSphere sphere;
|
||||
stream.Read(sphere);
|
||||
output.Write(sphere);
|
||||
}
|
||||
|
||||
// Skeleton
|
||||
{
|
||||
int32 nodesCount;
|
||||
stream.ReadInt32(&nodesCount);
|
||||
output.WriteInt32(nodesCount);
|
||||
|
||||
// For each node
|
||||
for (int32 nodeIndex = 0; nodeIndex < nodesCount; nodeIndex++)
|
||||
{
|
||||
int32 parentIndex;
|
||||
stream.ReadInt32(&parentIndex);
|
||||
output.WriteInt32(parentIndex);
|
||||
|
||||
Transform localTransform;
|
||||
stream.Read(localTransform);
|
||||
output.Write(localTransform);
|
||||
|
||||
String name;
|
||||
stream.ReadString(&name, 71);
|
||||
output.WriteString(name, 71);
|
||||
}
|
||||
|
||||
int32 bonesCount;
|
||||
stream.ReadInt32(&bonesCount);
|
||||
output.WriteInt32(bonesCount);
|
||||
|
||||
// For each bone
|
||||
for (int32 boneIndex = 0; boneIndex < bonesCount; boneIndex++)
|
||||
{
|
||||
int32 parentIndex;
|
||||
stream.ReadInt32(&parentIndex);
|
||||
output.WriteInt32(parentIndex);
|
||||
|
||||
int32 nodeIndex;
|
||||
stream.ReadInt32(&nodeIndex);
|
||||
output.WriteInt32(nodeIndex);
|
||||
|
||||
Transform localTransform;
|
||||
stream.Read(localTransform);
|
||||
output.Write(localTransform);
|
||||
|
||||
Matrix offsetMatrix;
|
||||
stream.ReadBytes(&offsetMatrix, sizeof(Matrix));
|
||||
output.WriteBytes(&offsetMatrix, sizeof(Matrix));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Save new header data
|
||||
if (context.AllocateChunk(0))
|
||||
return true;
|
||||
context.Output.Header.Chunks[0]->Data.Copy(output.GetHandle(), output.GetPosition());
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Upgrade_3_To_4(AssetMigrationContext& context)
|
||||
{
|
||||
ASSERT(context.Input.SerializedVersion == 3 && context.Output.SerializedVersion == 4);
|
||||
|
||||
// Rewrite header chunk (added blend shapes count)
|
||||
byte lodCount;
|
||||
Array<uint16> meshesCounts;
|
||||
{
|
||||
const auto srcData = context.Input.Header.Chunks[0];
|
||||
if (srcData == nullptr || srcData->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing model header chunk");
|
||||
return true;
|
||||
}
|
||||
MemoryReadStream stream(srcData->Get(), srcData->Size());
|
||||
MemoryWriteStream output(srcData->Size());
|
||||
|
||||
// Min Screen Size
|
||||
float minScreenSize;
|
||||
stream.ReadFloat(&minScreenSize);
|
||||
output.WriteFloat(minScreenSize);
|
||||
|
||||
// Amount of material slots
|
||||
int32 materialSlotsCount;
|
||||
stream.ReadInt32(&materialSlotsCount);
|
||||
output.WriteInt32(materialSlotsCount);
|
||||
|
||||
// For each material slot
|
||||
for (int32 materialSlotIndex = 0; materialSlotIndex < materialSlotsCount; materialSlotIndex++)
|
||||
{
|
||||
// Material
|
||||
Guid materialId;
|
||||
stream.Read(materialId);
|
||||
output.Write(materialId);
|
||||
|
||||
// Shadows Mode
|
||||
output.WriteByte(stream.ReadByte());
|
||||
|
||||
// Name
|
||||
String name;
|
||||
stream.ReadString(&name, 11);
|
||||
output.WriteString(name, 11);
|
||||
}
|
||||
|
||||
// Amount of LODs
|
||||
stream.ReadByte(&lodCount);
|
||||
output.WriteByte(lodCount);
|
||||
meshesCounts.Resize(lodCount);
|
||||
|
||||
// For each LOD
|
||||
for (int32 lodIndex = 0; lodIndex < lodCount; lodIndex++)
|
||||
{
|
||||
// Screen Size
|
||||
float screenSize;
|
||||
stream.ReadFloat(&screenSize);
|
||||
output.WriteFloat(screenSize);
|
||||
|
||||
// Amount of meshes
|
||||
uint16 meshesCount;
|
||||
stream.ReadUint16(&meshesCount);
|
||||
output.WriteUint16(meshesCount);
|
||||
meshesCounts[lodIndex] = meshesCount;
|
||||
|
||||
// For each mesh
|
||||
for (uint16 meshIndex = 0; meshIndex < meshesCount; meshIndex++)
|
||||
{
|
||||
// Material Slot index
|
||||
int32 materialSlotIndex;
|
||||
stream.ReadInt32(&materialSlotIndex);
|
||||
output.WriteInt32(materialSlotIndex);
|
||||
|
||||
// Box
|
||||
BoundingBox box;
|
||||
stream.Read(box);
|
||||
output.Write(box);
|
||||
|
||||
// Sphere
|
||||
BoundingSphere sphere;
|
||||
stream.Read(sphere);
|
||||
output.Write(sphere);
|
||||
|
||||
// Blend Shapes
|
||||
output.WriteUint16(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Skeleton
|
||||
{
|
||||
int32 nodesCount;
|
||||
stream.ReadInt32(&nodesCount);
|
||||
output.WriteInt32(nodesCount);
|
||||
|
||||
// For each node
|
||||
for (int32 nodeIndex = 0; nodeIndex < nodesCount; nodeIndex++)
|
||||
{
|
||||
int32 parentIndex;
|
||||
stream.ReadInt32(&parentIndex);
|
||||
output.WriteInt32(parentIndex);
|
||||
|
||||
Transform localTransform;
|
||||
stream.Read(localTransform);
|
||||
output.Write(localTransform);
|
||||
|
||||
String name;
|
||||
stream.ReadString(&name, 71);
|
||||
output.WriteString(name, 71);
|
||||
}
|
||||
|
||||
int32 bonesCount;
|
||||
stream.ReadInt32(&bonesCount);
|
||||
output.WriteInt32(bonesCount);
|
||||
|
||||
// For each bone
|
||||
for (int32 boneIndex = 0; boneIndex < bonesCount; boneIndex++)
|
||||
{
|
||||
int32 parentIndex;
|
||||
stream.ReadInt32(&parentIndex);
|
||||
output.WriteInt32(parentIndex);
|
||||
|
||||
int32 nodeIndex;
|
||||
stream.ReadInt32(&nodeIndex);
|
||||
output.WriteInt32(nodeIndex);
|
||||
|
||||
Transform localTransform;
|
||||
stream.Read(localTransform);
|
||||
output.Write(localTransform);
|
||||
|
||||
Matrix offsetMatrix;
|
||||
stream.ReadBytes(&offsetMatrix, sizeof(Matrix));
|
||||
output.WriteBytes(&offsetMatrix, sizeof(Matrix));
|
||||
}
|
||||
}
|
||||
|
||||
// Save new data
|
||||
if (stream.GetPosition() != stream.GetLength())
|
||||
{
|
||||
LOG(Error, "Invalid position after upgrading skinned model header data.");
|
||||
return true;
|
||||
}
|
||||
if (context.AllocateChunk(0))
|
||||
return true;
|
||||
context.Output.Header.Chunks[0]->Data.Copy(output.GetHandle(), output.GetPosition());
|
||||
}
|
||||
|
||||
// Rewrite meshes data chunks (blend shapes added)
|
||||
for (int32 lodIndex = 0; lodIndex < lodCount; lodIndex++)
|
||||
{
|
||||
const int32 chunkIndex = lodIndex + 1;
|
||||
const auto srcData = context.Input.Header.Chunks[chunkIndex];
|
||||
if (srcData == nullptr || srcData->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing skinned model LOD meshes data chunk");
|
||||
return true;
|
||||
}
|
||||
MemoryReadStream stream(srcData->Get(), srcData->Size());
|
||||
MemoryWriteStream output(srcData->Size());
|
||||
|
||||
for (int32 meshIndex = 0; meshIndex < meshesCounts[lodIndex]; meshIndex++)
|
||||
{
|
||||
uint32 vertices;
|
||||
stream.ReadUint32(&vertices);
|
||||
output.WriteUint32(vertices);
|
||||
uint32 triangles;
|
||||
stream.ReadUint32(&triangles);
|
||||
output.WriteUint32(triangles);
|
||||
uint16 blendShapesCount = 0;
|
||||
output.WriteUint16(blendShapesCount);
|
||||
const uint32 indicesCount = triangles * 3;
|
||||
const bool use16BitIndexBuffer = indicesCount <= MAX_uint16;
|
||||
const uint32 ibStride = use16BitIndexBuffer ? sizeof(uint16) : sizeof(uint32);
|
||||
if (vertices == 0 || triangles == 0)
|
||||
return true;
|
||||
const auto vb0 = stream.Move<VB0SkinnedElementType>(vertices);
|
||||
output.WriteBytes(vb0, vertices * sizeof(VB0SkinnedElementType));
|
||||
const auto ib = stream.Move<byte>(indicesCount * ibStride);
|
||||
output.WriteBytes(ib, indicesCount * ibStride);
|
||||
}
|
||||
|
||||
// Save new data
|
||||
if (stream.GetPosition() != stream.GetLength())
|
||||
{
|
||||
LOG(Error, "Invalid position after upgrading skinned model LOD meshes data.");
|
||||
return true;
|
||||
}
|
||||
if (context.AllocateChunk(chunkIndex))
|
||||
return true;
|
||||
context.Output.Header.Chunks[chunkIndex]->Data.Copy(output.GetHandle(), output.GetPosition());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Upgrade_4_To_5(AssetMigrationContext& context)
|
||||
{
|
||||
ASSERT(context.Input.SerializedVersion == 4 && context.Output.SerializedVersion == 5);
|
||||
|
||||
// Changes:
|
||||
// - added version number to header (for easier changes in future)
|
||||
// - added version number to mesh data (for easier changes in future)
|
||||
// - added skeleton retarget setups to header
|
||||
|
||||
// Rewrite header chunk (added header version and retarget entries)
|
||||
byte lodCount;
|
||||
Array<uint16> meshesCounts;
|
||||
{
|
||||
const auto srcData = context.Input.Header.Chunks[0];
|
||||
if (srcData == nullptr || srcData->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing model header chunk");
|
||||
return true;
|
||||
}
|
||||
MemoryReadStream stream(srcData->Get(), srcData->Size());
|
||||
MemoryWriteStream output(srcData->Size());
|
||||
|
||||
// Header Version
|
||||
output.WriteByte(1);
|
||||
|
||||
// Min Screen Size
|
||||
float minScreenSize;
|
||||
stream.ReadFloat(&minScreenSize);
|
||||
output.WriteFloat(minScreenSize);
|
||||
|
||||
// Amount of material slots
|
||||
int32 materialSlotsCount;
|
||||
stream.ReadInt32(&materialSlotsCount);
|
||||
output.WriteInt32(materialSlotsCount);
|
||||
|
||||
// For each material slot
|
||||
for (int32 materialSlotIndex = 0; materialSlotIndex < materialSlotsCount; materialSlotIndex++)
|
||||
{
|
||||
// Material
|
||||
Guid materialId;
|
||||
stream.Read(materialId);
|
||||
output.Write(materialId);
|
||||
|
||||
// Shadows Mode
|
||||
output.WriteByte(stream.ReadByte());
|
||||
|
||||
// Name
|
||||
String name;
|
||||
stream.ReadString(&name, 11);
|
||||
output.WriteString(name, 11);
|
||||
}
|
||||
|
||||
// Amount of LODs
|
||||
stream.ReadByte(&lodCount);
|
||||
output.WriteByte(lodCount);
|
||||
meshesCounts.Resize(lodCount);
|
||||
|
||||
// For each LOD
|
||||
for (int32 lodIndex = 0; lodIndex < lodCount; lodIndex++)
|
||||
{
|
||||
// Screen Size
|
||||
float screenSize;
|
||||
stream.ReadFloat(&screenSize);
|
||||
output.WriteFloat(screenSize);
|
||||
|
||||
// Amount of meshes
|
||||
uint16 meshesCount;
|
||||
stream.ReadUint16(&meshesCount);
|
||||
output.WriteUint16(meshesCount);
|
||||
meshesCounts[lodIndex] = meshesCount;
|
||||
|
||||
// For each mesh
|
||||
for (uint16 meshIndex = 0; meshIndex < meshesCount; meshIndex++)
|
||||
{
|
||||
// Material Slot index
|
||||
int32 materialSlotIndex;
|
||||
stream.ReadInt32(&materialSlotIndex);
|
||||
output.WriteInt32(materialSlotIndex);
|
||||
|
||||
// Box
|
||||
BoundingBox box;
|
||||
stream.Read(box);
|
||||
output.Write(box);
|
||||
|
||||
// Sphere
|
||||
BoundingSphere sphere;
|
||||
stream.Read(sphere);
|
||||
output.Write(sphere);
|
||||
|
||||
// Blend Shapes
|
||||
uint16 blendShapes;
|
||||
stream.ReadUint16(&blendShapes);
|
||||
output.WriteUint16(blendShapes);
|
||||
for (int32 blendShapeIndex = 0; blendShapeIndex < blendShapes; blendShapeIndex++)
|
||||
{
|
||||
String blendShapeName;
|
||||
stream.ReadString(&blendShapeName, 13);
|
||||
output.WriteString(blendShapeName, 13);
|
||||
float blendShapeWeight;
|
||||
stream.ReadFloat(&blendShapeWeight);
|
||||
output.WriteFloat(blendShapeWeight);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Skeleton
|
||||
{
|
||||
int32 nodesCount;
|
||||
stream.ReadInt32(&nodesCount);
|
||||
output.WriteInt32(nodesCount);
|
||||
|
||||
// For each node
|
||||
for (int32 nodeIndex = 0; nodeIndex < nodesCount; nodeIndex++)
|
||||
{
|
||||
int32 parentIndex;
|
||||
stream.ReadInt32(&parentIndex);
|
||||
output.WriteInt32(parentIndex);
|
||||
|
||||
Transform localTransform;
|
||||
stream.Read(localTransform);
|
||||
output.Write(localTransform);
|
||||
|
||||
String name;
|
||||
stream.ReadString(&name, 71);
|
||||
output.WriteString(name, 71);
|
||||
}
|
||||
|
||||
int32 bonesCount;
|
||||
stream.ReadInt32(&bonesCount);
|
||||
output.WriteInt32(bonesCount);
|
||||
|
||||
// For each bone
|
||||
for (int32 boneIndex = 0; boneIndex < bonesCount; boneIndex++)
|
||||
{
|
||||
int32 parentIndex;
|
||||
stream.ReadInt32(&parentIndex);
|
||||
output.WriteInt32(parentIndex);
|
||||
|
||||
int32 nodeIndex;
|
||||
stream.ReadInt32(&nodeIndex);
|
||||
output.WriteInt32(nodeIndex);
|
||||
|
||||
Transform localTransform;
|
||||
stream.Read(localTransform);
|
||||
output.Write(localTransform);
|
||||
|
||||
Matrix offsetMatrix;
|
||||
stream.ReadBytes(&offsetMatrix, sizeof(Matrix));
|
||||
output.WriteBytes(&offsetMatrix, sizeof(Matrix));
|
||||
}
|
||||
}
|
||||
|
||||
// Retargeting
|
||||
{
|
||||
output.WriteInt32(0);
|
||||
}
|
||||
|
||||
// Save new data
|
||||
if (stream.GetPosition() != stream.GetLength())
|
||||
{
|
||||
LOG(Error, "Invalid position after upgrading skinned model header data.");
|
||||
return true;
|
||||
}
|
||||
if (context.AllocateChunk(0))
|
||||
return true;
|
||||
context.Output.Header.Chunks[0]->Data.Copy(output.GetHandle(), output.GetPosition());
|
||||
}
|
||||
|
||||
// Rewrite meshes data chunks
|
||||
for (int32 lodIndex = 0; lodIndex < lodCount; lodIndex++)
|
||||
{
|
||||
const int32 chunkIndex = lodIndex + 1;
|
||||
const auto srcData = context.Input.Header.Chunks[chunkIndex];
|
||||
if (srcData == nullptr || srcData->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing skinned model LOD meshes data chunk");
|
||||
return true;
|
||||
}
|
||||
MemoryReadStream stream(srcData->Get(), srcData->Size());
|
||||
MemoryWriteStream output(srcData->Size());
|
||||
|
||||
// Mesh Data Version
|
||||
output.WriteByte(1);
|
||||
|
||||
for (int32 meshIndex = 0; meshIndex < meshesCounts[lodIndex]; meshIndex++)
|
||||
{
|
||||
uint32 vertices;
|
||||
stream.ReadUint32(&vertices);
|
||||
output.WriteUint32(vertices);
|
||||
uint32 triangles;
|
||||
stream.ReadUint32(&triangles);
|
||||
output.WriteUint32(triangles);
|
||||
uint16 blendShapesCount;
|
||||
stream.ReadUint16(&blendShapesCount);
|
||||
output.WriteUint16(blendShapesCount);
|
||||
for (int32 blendShapeIndex = 0; blendShapeIndex < blendShapesCount; blendShapeIndex++)
|
||||
{
|
||||
output.WriteBool(stream.ReadBool());
|
||||
uint32 minVertexIndex, maxVertexIndex;
|
||||
stream.ReadUint32(&minVertexIndex);
|
||||
output.WriteUint32(minVertexIndex);
|
||||
stream.ReadUint32(&maxVertexIndex);
|
||||
output.WriteUint32(maxVertexIndex);
|
||||
uint32 blendShapeVertices;
|
||||
stream.ReadUint32(&blendShapeVertices);
|
||||
output.WriteUint32(blendShapeVertices);
|
||||
const uint32 blendShapeDataSize = blendShapeVertices * sizeof(BlendShapeVertex);
|
||||
const auto blendShapeData = stream.Move<byte>(blendShapeDataSize);
|
||||
output.WriteBytes(blendShapeData, blendShapeDataSize);
|
||||
}
|
||||
const uint32 indicesCount = triangles * 3;
|
||||
const bool use16BitIndexBuffer = indicesCount <= MAX_uint16;
|
||||
const uint32 ibStride = use16BitIndexBuffer ? sizeof(uint16) : sizeof(uint32);
|
||||
if (vertices == 0 || triangles == 0)
|
||||
return true;
|
||||
const auto vb0 = stream.Move<VB0SkinnedElementType>(vertices);
|
||||
output.WriteBytes(vb0, vertices * sizeof(VB0SkinnedElementType));
|
||||
const auto ib = stream.Move<byte>(indicesCount * ibStride);
|
||||
output.WriteBytes(ib, indicesCount * ibStride);
|
||||
}
|
||||
|
||||
// Save new data
|
||||
if (stream.GetPosition() != stream.GetLength())
|
||||
{
|
||||
LOG(Error, "Invalid position after upgrading skinned model LOD meshes data.");
|
||||
return true;
|
||||
}
|
||||
if (context.AllocateChunk(chunkIndex))
|
||||
return true;
|
||||
context.Output.Header.Chunks[chunkIndex]->Data.Copy(output.GetHandle(), output.GetPosition());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -5,19 +5,6 @@
|
||||
#if USE_EDITOR
|
||||
|
||||
#include "BinaryAssetUpgrader.h"
|
||||
#include "Engine/Core/Core.h"
|
||||
#include "Engine/Platform/Platform.h"
|
||||
#include "Engine/Graphics/RenderTools.h"
|
||||
#include "Engine/Content/Assets/CubeTexture.h"
|
||||
#include "Engine/Content/Assets/IESProfile.h"
|
||||
#include "Engine/Content/Assets/Texture.h"
|
||||
#include "Engine/Utilities/Encryption.h"
|
||||
#include "Engine/Serialization/JsonTools.h"
|
||||
#include "Engine/Serialization/MemoryReadStream.h"
|
||||
#include "Engine/Render2D/SpriteAtlas.h"
|
||||
#if USE_EDITOR
|
||||
#include "Editor/Content/PreviewsCache.h"
|
||||
#endif
|
||||
|
||||
/// <summary>
|
||||
/// Texture Asset Upgrader
|
||||
@@ -33,792 +20,10 @@ public:
|
||||
{
|
||||
static const Upgrader upgraders[] =
|
||||
{
|
||||
{ 1, 4, &Upgrade_1_To_4 },
|
||||
{},
|
||||
};
|
||||
setup(upgraders, ARRAY_COUNT(upgraders));
|
||||
}
|
||||
|
||||
private:
|
||||
// ============================================
|
||||
// Versions 1, 2 and 3:
|
||||
// Designed: long time ago in a galaxy far far away
|
||||
// Custom Data: not used
|
||||
// Chunk 0: Header (sprite atlas also stored sprites)
|
||||
// Chunk 1-14: Texture Mips
|
||||
// Chunk 15: Texture Import options
|
||||
// ============================================
|
||||
//
|
||||
// Note: we merge CubeTexture, Texture, AssetPreviewsCache, IESProfile and AssetSpriteAtlas storage backend.
|
||||
// This simplifies textures operations like importing/exporting and allows to reduce amount of code to maintain.
|
||||
//
|
||||
// Firstly store texture header inside a CustomData field and get it just after asset creation.
|
||||
// Secondly move texture import metadata (format, max size, etc.) to the json metadata.
|
||||
// Lastly store all texture mips in chunks 1-14 and use 15th and 16th chunk for custom data per asset type (sprites or thumbnails meta, etc.).
|
||||
// Note: mips order has been changed, Chunk[0..13] contain now Mip[0..13]. Internal storage layer should manage data chunks order inside a file, not an asset.
|
||||
// Additionally texture header contains a few bytes to be used by the assets (for eg. IES Profile uses it to store Brightness parameter)
|
||||
//
|
||||
// Old AssetPreviewsCache:
|
||||
// Chunk 0: header
|
||||
// Chunk 1: assets ID table
|
||||
// Chunk 2: atlas image
|
||||
// ============================================
|
||||
// Version 4:
|
||||
// Designed: 4/25/2017
|
||||
// Custom Data: Header
|
||||
// Metadata: Import Options
|
||||
// Chunk 0-13: Mips (from the highest quality to the lowest)
|
||||
// Chunk 15: Custom Asset Data:
|
||||
// - AssetSpriteAtlas: sprites
|
||||
// - AssetPreviewsCache: asset previews meta
|
||||
// ============================================
|
||||
|
||||
enum class PixelFormatOld
|
||||
{
|
||||
PF_Unknown = 0,
|
||||
PF_R8G8B8A8 = 1,
|
||||
PF_R16G16B16A16 = 2,
|
||||
PF_R32G32B32A32 = 3,
|
||||
PF_A8 = 4,
|
||||
PF_R16F = 5,
|
||||
PF_R32 = 6,
|
||||
PF_R16G16 = 7,
|
||||
PF_R32G32 = 8,
|
||||
PF_R10G10B10A2 = 9,
|
||||
PF_R11G11B10 = 10,
|
||||
PF_BC1 = 11,
|
||||
PF_BC2 = 12,
|
||||
PF_BC3 = 13,
|
||||
PF_BC4 = 14,
|
||||
PF_BC5 = 15,
|
||||
PF_B8G8R8A8 = 16,
|
||||
PF_DepthStencil = 17,
|
||||
PF_ShadowDepth = 18,
|
||||
PF_D16 = 19,
|
||||
PF_D24 = 20,
|
||||
PF_D32 = 21,
|
||||
PF_R16 = 22,
|
||||
PF_B5G6R5 = 23,
|
||||
PF_R8G8_SNORM = 24,
|
||||
PF_R8G8_UNORM = 25,
|
||||
};
|
||||
|
||||
static PixelFormat PixelFormatOldToNew(PixelFormatOld format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case PixelFormatOld::PF_Unknown:
|
||||
return PixelFormat::Unknown;
|
||||
case PixelFormatOld::PF_R8G8B8A8:
|
||||
return PixelFormat::R8G8B8A8_UNorm;
|
||||
case PixelFormatOld::PF_R16G16B16A16:
|
||||
return PixelFormat::R16G16B16A16_Float;
|
||||
case PixelFormatOld::PF_R32G32B32A32:
|
||||
return PixelFormat::R32G32B32A32_Float;
|
||||
case PixelFormatOld::PF_A8:
|
||||
return PixelFormat::A8_UNorm;
|
||||
case PixelFormatOld::PF_R16F:
|
||||
return PixelFormat::R16_Float;
|
||||
case PixelFormatOld::PF_R32:
|
||||
return PixelFormat::R32_Float;
|
||||
case PixelFormatOld::PF_R16G16:
|
||||
return PixelFormat::R16G16_Float;
|
||||
case PixelFormatOld::PF_R32G32:
|
||||
return PixelFormat::R32G32_Float;
|
||||
case PixelFormatOld::PF_R10G10B10A2:
|
||||
return PixelFormat::R10G10B10A2_UNorm;
|
||||
case PixelFormatOld::PF_R11G11B10:
|
||||
return PixelFormat::R11G11B10_Float;
|
||||
case PixelFormatOld::PF_BC1:
|
||||
return PixelFormat::BC1_UNorm;
|
||||
case PixelFormatOld::PF_BC2:
|
||||
return PixelFormat::BC2_UNorm;
|
||||
case PixelFormatOld::PF_BC3:
|
||||
return PixelFormat::BC3_UNorm;
|
||||
case PixelFormatOld::PF_BC4:
|
||||
return PixelFormat::BC4_UNorm;
|
||||
case PixelFormatOld::PF_BC5:
|
||||
return PixelFormat::BC5_UNorm;
|
||||
case PixelFormatOld::PF_B8G8R8A8:
|
||||
return PixelFormat::B8G8R8A8_UNorm;
|
||||
case PixelFormatOld::PF_DepthStencil:
|
||||
return PixelFormat::D24_UNorm_S8_UInt;
|
||||
case PixelFormatOld::PF_ShadowDepth:
|
||||
return PixelFormat::D32_Float;
|
||||
case PixelFormatOld::PF_D16:
|
||||
return PixelFormat::D16_UNorm;
|
||||
case PixelFormatOld::PF_D24:
|
||||
return PixelFormat::D24_UNorm_S8_UInt;
|
||||
case PixelFormatOld::PF_D32:
|
||||
return PixelFormat::D32_Float;
|
||||
case PixelFormatOld::PF_R16:
|
||||
return PixelFormat::R16_UNorm;
|
||||
case PixelFormatOld::PF_B5G6R5:
|
||||
return PixelFormat::B5G6R5_UNorm;
|
||||
case PixelFormatOld::PF_R8G8_SNORM:
|
||||
return PixelFormat::R8G8_SNorm;
|
||||
case PixelFormatOld::PF_R8G8_UNORM:
|
||||
return PixelFormat::R8G8_UNorm;
|
||||
default: ;
|
||||
}
|
||||
|
||||
CRASH;
|
||||
return PixelFormat::Unknown;
|
||||
}
|
||||
|
||||
static PixelFormatOld PixelFormatToOld(PixelFormat format)
|
||||
{
|
||||
switch (format)
|
||||
{
|
||||
case PixelFormat::Unknown:
|
||||
return PixelFormatOld::PF_Unknown;
|
||||
case PixelFormat::R32G32B32A32_Typeless:
|
||||
case PixelFormat::R32G32B32A32_Float:
|
||||
case PixelFormat::R32G32B32A32_UInt:
|
||||
case PixelFormat::R32G32B32A32_SInt:
|
||||
return PixelFormatOld::PF_R32G32B32A32;
|
||||
//case PixelFormat::R32G32B32_Typeless:
|
||||
//case PixelFormat::R32G32B32_Float:
|
||||
//case PixelFormat::R32G32B32_UInt:
|
||||
//case PixelFormat::R32G32B32_SInt:
|
||||
case PixelFormat::R16G16B16A16_Typeless:
|
||||
case PixelFormat::R16G16B16A16_Float:
|
||||
case PixelFormat::R16G16B16A16_UNorm:
|
||||
case PixelFormat::R16G16B16A16_UInt:
|
||||
case PixelFormat::R16G16B16A16_SNorm:
|
||||
case PixelFormat::R16G16B16A16_SInt:
|
||||
return PixelFormatOld::PF_R16G16B16A16;
|
||||
case PixelFormat::R32G32_Typeless:
|
||||
case PixelFormat::R32G32_Float:
|
||||
case PixelFormat::R32G32_UInt:
|
||||
case PixelFormat::R32G32_SInt:
|
||||
case PixelFormat::R32G8X24_Typeless:
|
||||
return PixelFormatOld::PF_R32G32;
|
||||
case PixelFormat::D32_Float_S8X24_UInt:
|
||||
case PixelFormat::R32_Float_X8X24_Typeless:
|
||||
case PixelFormat::X32_Typeless_G8X24_UInt:
|
||||
return PixelFormatOld::PF_R32G32B32A32;
|
||||
case PixelFormat::R10G10B10A2_Typeless:
|
||||
case PixelFormat::R10G10B10A2_UNorm:
|
||||
case PixelFormat::R10G10B10A2_UInt:
|
||||
return PixelFormatOld::PF_R10G10B10A2;
|
||||
case PixelFormat::R11G11B10_Float:
|
||||
return PixelFormatOld::PF_R11G11B10;
|
||||
case PixelFormat::R8G8B8A8_Typeless:
|
||||
case PixelFormat::R8G8B8A8_UNorm:
|
||||
case PixelFormat::R8G8B8A8_UNorm_sRGB:
|
||||
case PixelFormat::R8G8B8A8_UInt:
|
||||
case PixelFormat::R8G8B8A8_SNorm:
|
||||
case PixelFormat::R8G8B8A8_SInt:
|
||||
return PixelFormatOld::PF_R8G8B8A8;
|
||||
case PixelFormat::R16G16_Typeless:
|
||||
case PixelFormat::R16G16_Float:
|
||||
case PixelFormat::R16G16_UNorm:
|
||||
case PixelFormat::R16G16_UInt:
|
||||
case PixelFormat::R16G16_SNorm:
|
||||
case PixelFormat::R16G16_SInt:
|
||||
return PixelFormatOld::PF_R16G16;
|
||||
case PixelFormat::R32_Typeless:
|
||||
return PixelFormatOld::PF_R32;
|
||||
case PixelFormat::D32_Float:
|
||||
return PixelFormatOld::PF_DepthStencil;
|
||||
case PixelFormat::R32_Float:
|
||||
case PixelFormat::R32_UInt:
|
||||
case PixelFormat::R32_SInt:
|
||||
return PixelFormatOld::PF_R32;
|
||||
case PixelFormat::R24G8_Typeless:
|
||||
case PixelFormat::D24_UNorm_S8_UInt:
|
||||
case PixelFormat::R24_UNorm_X8_Typeless:
|
||||
return PixelFormatOld::PF_DepthStencil;
|
||||
//case PixelFormat::X24_Typeless_G8_UInt:
|
||||
case PixelFormat::R8G8_Typeless:
|
||||
case PixelFormat::R8G8_UNorm:
|
||||
case PixelFormat::R8G8_UInt:
|
||||
return PixelFormatOld::PF_R8G8_UNORM;
|
||||
case PixelFormat::R8G8_SNorm:
|
||||
case PixelFormat::R8G8_SInt:
|
||||
return PixelFormatOld::PF_R8G8_SNORM;
|
||||
case PixelFormat::R16_Float:
|
||||
return PixelFormatOld::PF_R16F;
|
||||
case PixelFormat::R16_Typeless:
|
||||
case PixelFormat::D16_UNorm:
|
||||
case PixelFormat::R16_UNorm:
|
||||
case PixelFormat::R16_UInt:
|
||||
case PixelFormat::R16_SNorm:
|
||||
case PixelFormat::R16_SInt:
|
||||
return PixelFormatOld::PF_R16;
|
||||
case PixelFormat::R8_Typeless:
|
||||
case PixelFormat::R8_UNorm:
|
||||
case PixelFormat::R8_UInt:
|
||||
case PixelFormat::R8_SNorm:
|
||||
case PixelFormat::R8_SInt:
|
||||
case PixelFormat::A8_UNorm:
|
||||
return PixelFormatOld::PF_A8;
|
||||
case PixelFormat::R1_UNorm:
|
||||
//case PixelFormat::R9G9B9E5_Sharedexp:
|
||||
//case PixelFormat::R8G8_B8G8_UNorm:
|
||||
//case PixelFormat::G8R8_G8B8_UNorm:
|
||||
case PixelFormat::BC1_Typeless:
|
||||
case PixelFormat::BC1_UNorm:
|
||||
case PixelFormat::BC1_UNorm_sRGB:
|
||||
return PixelFormatOld::PF_BC1;
|
||||
case PixelFormat::BC2_Typeless:
|
||||
case PixelFormat::BC2_UNorm:
|
||||
case PixelFormat::BC2_UNorm_sRGB:
|
||||
return PixelFormatOld::PF_BC2;
|
||||
case PixelFormat::BC3_Typeless:
|
||||
case PixelFormat::BC3_UNorm:
|
||||
case PixelFormat::BC3_UNorm_sRGB:
|
||||
return PixelFormatOld::PF_BC3;
|
||||
case PixelFormat::BC4_Typeless:
|
||||
case PixelFormat::BC4_UNorm:
|
||||
case PixelFormat::BC4_SNorm:
|
||||
return PixelFormatOld::PF_BC4;
|
||||
case PixelFormat::BC5_Typeless:
|
||||
case PixelFormat::BC5_UNorm:
|
||||
case PixelFormat::BC5_SNorm:
|
||||
return PixelFormatOld::PF_BC5;
|
||||
case PixelFormat::B5G6R5_UNorm:
|
||||
return PixelFormatOld::PF_B5G6R5;
|
||||
//case PixelFormat::B5G5R5A1_UNorm:
|
||||
//case PixelFormat::B8G8R8A8_UNorm:
|
||||
//case PixelFormat::B8G8R8X8_UNorm:
|
||||
//case PixelFormat::R10G10B10_Xr_Bias_A2_UNorm:
|
||||
//case PixelFormat::B8G8R8A8_Typeless:
|
||||
//case PixelFormat::B8G8R8A8_UNorm_sRGB:
|
||||
//case PixelFormat::B8G8R8X8_Typeless:
|
||||
//case PixelFormat::B8G8R8X8_UNorm_sRGB:
|
||||
//case PixelFormat::BC6H_Typeless:
|
||||
//case PixelFormat::BC6H_Uf16:
|
||||
//case PixelFormat::BC6H_Sf16:
|
||||
//case PixelFormat::BC7_Typeless:
|
||||
//case PixelFormat::BC7_UNorm:
|
||||
//case PixelFormat::BC7_UNorm_sRGB:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
CRASH;
|
||||
return PixelFormatOld::PF_Unknown;
|
||||
}
|
||||
|
||||
struct TextureHeader1
|
||||
{
|
||||
int32 Width;
|
||||
int32 Height;
|
||||
byte MipLevels;
|
||||
bool NeverStream;
|
||||
TextureFormatType Type;
|
||||
PixelFormatOld Format;
|
||||
bool IsSRGB;
|
||||
};
|
||||
|
||||
struct TextureHeader2
|
||||
{
|
||||
int32 Width;
|
||||
int32 Height;
|
||||
byte MipLevels;
|
||||
bool NeverStream;
|
||||
TextureFormatType Type;
|
||||
PixelFormatOld Format;
|
||||
bool IsSRGB;
|
||||
};
|
||||
|
||||
struct TextureHeader3
|
||||
{
|
||||
int32 Width;
|
||||
int32 Height;
|
||||
int32 MipLevels;
|
||||
bool IsCubeMap;
|
||||
bool NeverStream;
|
||||
TextureFormatType Type;
|
||||
PixelFormat Format;
|
||||
bool IsSRGB;
|
||||
};
|
||||
|
||||
struct CubeTextureHeader1
|
||||
{
|
||||
int32 Size;
|
||||
byte MipLevels;
|
||||
PixelFormatOld Format;
|
||||
bool IsSRGB;
|
||||
};
|
||||
|
||||
enum class TextureOwnerType1
|
||||
{
|
||||
Texture,
|
||||
CubeTexture,
|
||||
SpriteAtlas,
|
||||
IESProfile,
|
||||
PreviewsCache,
|
||||
};
|
||||
|
||||
static bool GetOwnerType(AssetMigrationContext& context, TextureOwnerType1& type)
|
||||
{
|
||||
auto typeName = context.Input.Header.TypeName;
|
||||
|
||||
if (typeName == Texture::TypeName)
|
||||
{
|
||||
type = TextureOwnerType1::Texture;
|
||||
return false;
|
||||
}
|
||||
if (typeName == CubeTexture::TypeName)
|
||||
{
|
||||
type = TextureOwnerType1::CubeTexture;
|
||||
return false;
|
||||
}
|
||||
if (typeName == SpriteAtlas::TypeName)
|
||||
{
|
||||
type = TextureOwnerType1::SpriteAtlas;
|
||||
return false;
|
||||
}
|
||||
if (typeName == IESProfile::TypeName)
|
||||
{
|
||||
type = TextureOwnerType1::IESProfile;
|
||||
return false;
|
||||
}
|
||||
#if USE_EDITOR
|
||||
if (typeName == PreviewsCache::TypeName)
|
||||
{
|
||||
type = TextureOwnerType1::PreviewsCache;
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
LOG(Warning, "Invalid input asset type.");
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool Upgrade_1_To_4_ImportOptions(AssetMigrationContext& context)
|
||||
{
|
||||
// Check if has no 15th chunk
|
||||
auto chunk = context.Input.Header.Chunks[15];
|
||||
if (chunk == nullptr || chunk->IsMissing())
|
||||
return false;
|
||||
|
||||
#if USE_EDITOR
|
||||
|
||||
// Get import metadata json
|
||||
rapidjson_flax::Document importMeta;
|
||||
if (context.Input.Metadata.IsValid())
|
||||
{
|
||||
importMeta.Parse((const char*)context.Input.Metadata.Get(), context.Input.Metadata.Length());
|
||||
if (importMeta.HasParseError())
|
||||
{
|
||||
LOG(Warning, "Failed to parse import meta json.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Get import options json
|
||||
rapidjson_flax::Document importOptions;
|
||||
{
|
||||
// Decrypt bytes
|
||||
int32 length = chunk->Size();
|
||||
Encryption::DecryptBytes(chunk->Get(), length);
|
||||
|
||||
// Load Json
|
||||
static_assert(sizeof(char) == sizeof(rapidjson_flax::Document::Ch), "Invalid rapidJson document char size.");
|
||||
int32 tmpJsonSize = length;
|
||||
importOptions.Parse((const char*)chunk->Get(), tmpJsonSize);
|
||||
if (importOptions.HasParseError())
|
||||
{
|
||||
LOG(Warning, "Failed to parse import options json.");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// Merge deprecated json meta from chunk 15 with import metadata
|
||||
JsonTools::MergeDocuments(importMeta, importOptions);
|
||||
|
||||
// Save json metadata
|
||||
{
|
||||
rapidjson_flax::StringBuffer buffer;
|
||||
rapidjson_flax::Writer<rapidjson_flax::StringBuffer> writer(buffer);
|
||||
if (!importMeta.Accept(writer))
|
||||
{
|
||||
LOG(Warning, "Failed to serialize metadata json.");
|
||||
return true;
|
||||
}
|
||||
context.Output.Metadata.Copy((const byte*)buffer.GetString(), (uint32)buffer.GetSize());
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Upgrade_1_To_4_Texture(AssetMigrationContext& context)
|
||||
{
|
||||
// Get texture header
|
||||
auto headerChunk = context.Input.Header.Chunks[0];
|
||||
if (headerChunk == nullptr || headerChunk->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing texture header chunk.");
|
||||
return true;
|
||||
}
|
||||
MemoryReadStream headerStream(headerChunk->Get(), headerChunk->Size());
|
||||
|
||||
// Load texture header
|
||||
int32 textureHeaderVersion;
|
||||
headerStream.ReadInt32(&textureHeaderVersion);
|
||||
if (textureHeaderVersion != 1)
|
||||
{
|
||||
LOG(Warning, "Invalid texture header version.");
|
||||
return true;
|
||||
}
|
||||
TextureHeader1 textureHeader;
|
||||
headerStream.ReadBytes(&textureHeader, sizeof(textureHeader));
|
||||
|
||||
// Create new header
|
||||
TextureHeader newHeader;
|
||||
newHeader.Width = textureHeader.Width;
|
||||
newHeader.Height = textureHeader.Height;
|
||||
newHeader.MipLevels = textureHeader.MipLevels;
|
||||
newHeader.Format = PixelFormatOldToNew(textureHeader.Format);
|
||||
newHeader.IsSRGB = textureHeader.IsSRGB;
|
||||
newHeader.NeverStream = textureHeader.NeverStream;
|
||||
newHeader.Type = textureHeader.Type;
|
||||
context.Output.CustomData.Copy(&newHeader);
|
||||
|
||||
// Convert import options
|
||||
if (Upgrade_1_To_4_ImportOptions(context))
|
||||
return true;
|
||||
|
||||
// Copy mip maps
|
||||
for (int32 mipIndex = 0; mipIndex < newHeader.MipLevels; mipIndex++)
|
||||
{
|
||||
auto srcChunk = context.Input.Header.Chunks[newHeader.MipLevels - mipIndex];
|
||||
if (srcChunk == nullptr || srcChunk->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing data chunk with a mipmap");
|
||||
return true;
|
||||
}
|
||||
if (context.AllocateChunk(mipIndex))
|
||||
return true;
|
||||
auto dstChunk = context.Output.Header.Chunks[mipIndex];
|
||||
|
||||
dstChunk->Data.Copy(srcChunk->Data);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Upgrade_1_To_4_CubeTexture(AssetMigrationContext& context)
|
||||
{
|
||||
// Get texture header
|
||||
auto headerChunk = context.Input.Header.Chunks[0];
|
||||
if (headerChunk == nullptr || headerChunk->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing cube texture header chunk.");
|
||||
return true;
|
||||
}
|
||||
MemoryReadStream headerStream(headerChunk->Get(), headerChunk->Size());
|
||||
|
||||
// Load texture header
|
||||
int32 textureHeaderVersion;
|
||||
headerStream.ReadInt32(&textureHeaderVersion);
|
||||
if (textureHeaderVersion != 1)
|
||||
{
|
||||
LOG(Warning, "Invalid cube texture header version.");
|
||||
return true;
|
||||
}
|
||||
CubeTextureHeader1 textureHeader;
|
||||
headerStream.ReadBytes(&textureHeader, sizeof(textureHeader));
|
||||
|
||||
// Create new header
|
||||
TextureHeader newHeader;
|
||||
newHeader.Width = textureHeader.Size;
|
||||
newHeader.Height = textureHeader.Size;
|
||||
newHeader.MipLevels = textureHeader.MipLevels;
|
||||
newHeader.Format = PixelFormatOldToNew(textureHeader.Format);
|
||||
newHeader.IsSRGB = textureHeader.IsSRGB;
|
||||
newHeader.Type = TextureFormatType::ColorRGB;
|
||||
newHeader.IsCubeMap = true;
|
||||
context.Output.CustomData.Copy(&newHeader);
|
||||
|
||||
// Convert import options
|
||||
if (Upgrade_1_To_4_ImportOptions(context))
|
||||
return true;
|
||||
|
||||
// Conversion from single chunk to normal texture chunks mapping mode (single mip per chunk)
|
||||
{
|
||||
auto cubeTextureData = context.Input.Header.Chunks[1];
|
||||
if (cubeTextureData == nullptr || cubeTextureData->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing data chunk with a cubemap");
|
||||
return true;
|
||||
}
|
||||
uint32 dataSize = cubeTextureData->Size();
|
||||
auto data = cubeTextureData->Get();
|
||||
|
||||
auto mipLevels = textureHeader.MipLevels;
|
||||
auto textureSize = textureHeader.Size;
|
||||
ASSERT(mipLevels > 0 && mipLevels <= GPU_MAX_TEXTURE_MIP_LEVELS);
|
||||
ASSERT(textureSize > 0 && textureSize <= GPU_MAX_TEXTURE_SIZE);
|
||||
|
||||
//Platform::MemorySet(cubeTextureData.Get(), cubeTextureData.Length(), MAX_uint32);
|
||||
|
||||
byte* position = (byte*)data;
|
||||
for (int32 mipIndex = 0; mipIndex < mipLevels; mipIndex++)
|
||||
{
|
||||
uint32 mipSize = textureSize >> mipIndex;
|
||||
|
||||
uint32 rowPitch, slicePitch;
|
||||
RenderTools::ComputePitch(PixelFormatOldToNew(textureHeader.Format), mipSize, mipSize, rowPitch, slicePitch);
|
||||
|
||||
uint32 mipDataSize = slicePitch * 6;
|
||||
|
||||
// Create mip
|
||||
if (context.AllocateChunk(mipIndex))
|
||||
return true;
|
||||
auto dstChunk = context.Output.Header.Chunks[mipIndex];
|
||||
dstChunk->Data.Copy(position, mipDataSize);
|
||||
|
||||
position += mipDataSize;
|
||||
}
|
||||
ASSERT(dataSize == (uint32)(position - data));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Upgrade_1_To_4_SpriteAtlas(AssetMigrationContext& context)
|
||||
{
|
||||
// Get texture header
|
||||
auto headerChunk = context.Input.Header.Chunks[0];
|
||||
if (headerChunk == nullptr || headerChunk->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing texture header chunk.");
|
||||
return true;
|
||||
}
|
||||
MemoryReadStream headerStream(headerChunk->Get(), headerChunk->Size());
|
||||
|
||||
// Load texture header
|
||||
int32 textureHeaderVersion;
|
||||
headerStream.ReadInt32(&textureHeaderVersion);
|
||||
if (textureHeaderVersion != 1)
|
||||
{
|
||||
LOG(Warning, "Invalid texture header version.");
|
||||
return true;
|
||||
}
|
||||
TextureHeader1 textureHeader;
|
||||
headerStream.ReadBytes(&textureHeader, sizeof(textureHeader));
|
||||
|
||||
// Create new header
|
||||
TextureHeader newHeader;
|
||||
newHeader.Width = textureHeader.Width;
|
||||
newHeader.Height = textureHeader.Height;
|
||||
newHeader.MipLevels = textureHeader.MipLevels;
|
||||
newHeader.Format = PixelFormatOldToNew(textureHeader.Format);
|
||||
newHeader.IsSRGB = textureHeader.IsSRGB;
|
||||
newHeader.NeverStream = textureHeader.NeverStream;
|
||||
newHeader.Type = textureHeader.Type;
|
||||
context.Output.CustomData.Copy(&newHeader);
|
||||
|
||||
// Copy sprite atlas data from old header stream to chunk (chunk 15th)
|
||||
if (context.AllocateChunk(15))
|
||||
return true;
|
||||
context.Output.Header.Chunks[15]->Data.Copy(headerStream.GetPositionHandle(), headerStream.GetLength() - headerStream.GetPosition());
|
||||
|
||||
// Convert import options
|
||||
if (Upgrade_1_To_4_ImportOptions(context))
|
||||
return true;
|
||||
|
||||
// Copy mip maps
|
||||
for (int32 mipIndex = 0; mipIndex < newHeader.MipLevels; mipIndex++)
|
||||
{
|
||||
auto srcChunk = context.Input.Header.Chunks[newHeader.MipLevels - mipIndex];
|
||||
if (srcChunk == nullptr || srcChunk->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing data chunk with a mipmap");
|
||||
return true;
|
||||
}
|
||||
if (context.AllocateChunk(mipIndex))
|
||||
return true;
|
||||
auto dstChunk = context.Output.Header.Chunks[mipIndex];
|
||||
|
||||
dstChunk->Data.Copy(srcChunk->Data);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Upgrade_1_To_4_IESProfile(AssetMigrationContext& context)
|
||||
{
|
||||
// Get texture header
|
||||
auto headerChunk = context.Input.Header.Chunks[0];
|
||||
if (headerChunk == nullptr || headerChunk->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing IES profile texture header chunk.");
|
||||
return true;
|
||||
}
|
||||
MemoryReadStream headerStream(headerChunk->Get(), headerChunk->Size());
|
||||
|
||||
// Load IES header
|
||||
int32 iesHeaderVersion;
|
||||
headerStream.ReadInt32(&iesHeaderVersion);
|
||||
if (iesHeaderVersion != 1)
|
||||
{
|
||||
LOG(Warning, "Invalid IES profile header.");
|
||||
return true;
|
||||
}
|
||||
float brightness, multiplier;
|
||||
headerStream.ReadFloat(&brightness);
|
||||
headerStream.ReadFloat(&multiplier);
|
||||
|
||||
// Load texture header
|
||||
int32 textureHeaderVersion;
|
||||
headerStream.ReadInt32(&textureHeaderVersion);
|
||||
if (textureHeaderVersion != 1)
|
||||
{
|
||||
LOG(Warning, "Invalid texture header version.");
|
||||
return true;
|
||||
}
|
||||
TextureHeader1 textureHeader;
|
||||
headerStream.ReadBytes(&textureHeader, sizeof(textureHeader));
|
||||
if (textureHeader.MipLevels != 1)
|
||||
{
|
||||
LOG(Warning, "Invalid IES profile texture header.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create new header
|
||||
TextureHeader newHeader;
|
||||
newHeader.Width = textureHeader.Width;
|
||||
newHeader.Height = textureHeader.Height;
|
||||
newHeader.MipLevels = textureHeader.MipLevels;
|
||||
newHeader.Format = PixelFormatOldToNew(textureHeader.Format);
|
||||
newHeader.IsSRGB = textureHeader.IsSRGB;
|
||||
newHeader.NeverStream = textureHeader.NeverStream;
|
||||
newHeader.Type = textureHeader.Type;
|
||||
auto data = (IESProfile::CustomDataLayout*)newHeader.CustomData;
|
||||
data->Brightness = brightness;
|
||||
data->TextureMultiplier = multiplier;
|
||||
context.Output.CustomData.Copy(&newHeader);
|
||||
|
||||
// Convert import options
|
||||
if (Upgrade_1_To_4_ImportOptions(context))
|
||||
return true;
|
||||
|
||||
// Copy texture
|
||||
{
|
||||
auto srcChunk = context.Input.Header.Chunks[1];
|
||||
if (srcChunk == nullptr || srcChunk->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing data chunk with a mipmap");
|
||||
return true;
|
||||
}
|
||||
if (context.AllocateChunk(0))
|
||||
return true;
|
||||
auto dstChunk = context.Output.Header.Chunks[0];
|
||||
|
||||
dstChunk->Data.Copy(srcChunk->Data);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Upgrade_1_To_4_PreviewsCache(AssetMigrationContext& context)
|
||||
{
|
||||
// Get texture header
|
||||
auto headerChunk = context.Input.Header.Chunks[0];
|
||||
if (headerChunk == nullptr || headerChunk->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing texture header chunk.");
|
||||
return true;
|
||||
}
|
||||
MemoryReadStream headerStream(headerChunk->Get(), headerChunk->Size());
|
||||
|
||||
// Load atlas header
|
||||
struct AtlasHeader1
|
||||
{
|
||||
int32 Version;
|
||||
int32 TextureHeaderVersion;
|
||||
TextureHeader1 TextureHeader;
|
||||
};
|
||||
AtlasHeader1 atlasHeader;
|
||||
headerStream.ReadBytes(&atlasHeader, sizeof(atlasHeader));
|
||||
if (atlasHeader.Version != 1 || atlasHeader.TextureHeaderVersion != 1)
|
||||
{
|
||||
LOG(Warning, "Invalid asset previews header.");
|
||||
return true;
|
||||
}
|
||||
auto& textureHeader = atlasHeader.TextureHeader;
|
||||
if (textureHeader.MipLevels != 1)
|
||||
{
|
||||
LOG(Warning, "Invalid asset previews texture header.");
|
||||
return true;
|
||||
}
|
||||
|
||||
// Create new header
|
||||
TextureHeader newHeader;
|
||||
newHeader.Width = textureHeader.Width;
|
||||
newHeader.Height = textureHeader.Height;
|
||||
newHeader.MipLevels = textureHeader.MipLevels;
|
||||
newHeader.Format = PixelFormatOldToNew(textureHeader.Format);
|
||||
newHeader.IsSRGB = textureHeader.IsSRGB;
|
||||
newHeader.NeverStream = textureHeader.NeverStream;
|
||||
newHeader.Type = textureHeader.Type;
|
||||
context.Output.CustomData.Copy(&newHeader);
|
||||
|
||||
// Copy asset previews IDs mapping data from old chunk to new one
|
||||
auto idsChunk = context.Input.Header.Chunks[1];
|
||||
if (idsChunk == nullptr || idsChunk->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing asset previews IDs mapping data chunk.");
|
||||
return true;
|
||||
}
|
||||
if (context.AllocateChunk(15))
|
||||
return true;
|
||||
context.Output.Header.Chunks[15]->Data.Copy(idsChunk->Data);
|
||||
|
||||
// Convert import options
|
||||
if (Upgrade_1_To_4_ImportOptions(context))
|
||||
return true;
|
||||
|
||||
// Copy atlas image (older version has only single mip)
|
||||
{
|
||||
auto srcChunk = context.Input.Header.Chunks[2];
|
||||
if (srcChunk == nullptr || srcChunk->IsMissing())
|
||||
{
|
||||
LOG(Warning, "Missing data chunk with a mipmap");
|
||||
return true;
|
||||
}
|
||||
if (context.AllocateChunk(0))
|
||||
return true;
|
||||
auto dstChunk = context.Output.Header.Chunks[0];
|
||||
|
||||
dstChunk->Data.Copy(srcChunk->Data);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool Upgrade_1_To_4(AssetMigrationContext& context)
|
||||
{
|
||||
ASSERT(context.Input.SerializedVersion == 1 && context.Output.SerializedVersion == 4);
|
||||
|
||||
// Peek asset type
|
||||
TextureOwnerType1 type;
|
||||
if (GetOwnerType(context, type))
|
||||
return true;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case TextureOwnerType1::Texture:
|
||||
return Upgrade_1_To_4_Texture(context);
|
||||
case TextureOwnerType1::CubeTexture:
|
||||
return Upgrade_1_To_4_CubeTexture(context);
|
||||
case TextureOwnerType1::SpriteAtlas:
|
||||
return Upgrade_1_To_4_SpriteAtlas(context);
|
||||
case TextureOwnerType1::IESProfile:
|
||||
return Upgrade_1_To_4_IESProfile(context);
|
||||
case TextureOwnerType1::PreviewsCache:
|
||||
return Upgrade_1_To_4_PreviewsCache(context);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -97,55 +97,6 @@ void MeshData::InitFromModelVertices(ModelVertex19* vertices, uint32 verticesCou
|
||||
}
|
||||
}
|
||||
|
||||
void MeshData::InitFromModelVertices(ModelVertex18* vertices, uint32 verticesCount)
|
||||
{
|
||||
Positions.Resize(verticesCount, false);
|
||||
UVs.Resize(verticesCount, false);
|
||||
Normals.Resize(verticesCount, false);
|
||||
Tangents.Resize(verticesCount, false);
|
||||
BitangentSigns.Resize(0);
|
||||
LightmapUVs.Resize(verticesCount, false);
|
||||
Colors.Resize(0);
|
||||
BlendIndices.Resize(0);
|
||||
BlendWeights.Resize(0);
|
||||
BlendShapes.Resize(0);
|
||||
|
||||
for (uint32 i = 0; i < verticesCount; i++)
|
||||
{
|
||||
Positions[i] = vertices->Position;
|
||||
UVs[i] = vertices->TexCoord.ToFloat2();
|
||||
Normals[i] = vertices->Normal.ToFloat3() * 2.0f - 1.0f;
|
||||
Tangents[i] = vertices->Tangent.ToFloat3() * 2.0f - 1.0f;
|
||||
LightmapUVs[i] = vertices->LightmapUVs.ToFloat2();
|
||||
|
||||
vertices++;
|
||||
}
|
||||
}
|
||||
|
||||
void MeshData::InitFromModelVertices(ModelVertex15* vertices, uint32 verticesCount)
|
||||
{
|
||||
Positions.Resize(verticesCount, false);
|
||||
UVs.Resize(verticesCount, false);
|
||||
Normals.Resize(verticesCount, false);
|
||||
Tangents.Resize(verticesCount, false);
|
||||
BitangentSigns.Resize(0);
|
||||
LightmapUVs.Resize(0);
|
||||
Colors.Resize(0);
|
||||
BlendIndices.Resize(0);
|
||||
BlendWeights.Resize(0);
|
||||
BlendShapes.Resize(0);
|
||||
|
||||
for (uint32 i = 0; i < verticesCount; i++)
|
||||
{
|
||||
Positions[i] = vertices->Position;
|
||||
UVs[i] = vertices->TexCoord.ToFloat2();
|
||||
Normals[i] = vertices->Normal.ToFloat3() * 2.0f - 1.0f;
|
||||
Tangents[i] = vertices->Tangent.ToFloat3() * 2.0f - 1.0f;
|
||||
|
||||
vertices++;
|
||||
}
|
||||
}
|
||||
|
||||
void MeshData::InitFromModelVertices(VB0ElementType18* vb0, VB1ElementType18* vb1, uint32 verticesCount)
|
||||
{
|
||||
Positions.Resize(verticesCount, false);
|
||||
@@ -210,31 +161,6 @@ void MeshData::InitFromModelVertices(VB0ElementType18* vb0, VB1ElementType18* vb
|
||||
}
|
||||
}
|
||||
|
||||
void MeshData::InitFromModelVertices(VB0ElementType15* vb0, VB1ElementType15* vb1, uint32 verticesCount)
|
||||
{
|
||||
Positions.Resize(verticesCount, false);
|
||||
UVs.Resize(verticesCount, false);
|
||||
Normals.Resize(verticesCount, false);
|
||||
Tangents.Resize(verticesCount, false);
|
||||
BitangentSigns.Resize(0);
|
||||
LightmapUVs.Resize(0, false);
|
||||
Colors.Resize(0);
|
||||
BlendIndices.Resize(0);
|
||||
BlendWeights.Resize(0);
|
||||
BlendShapes.Resize(0);
|
||||
|
||||
for (uint32 i = 0; i < verticesCount; i++)
|
||||
{
|
||||
Positions[i] = vb0->Position;
|
||||
UVs[i] = vb1->TexCoord.ToFloat2();
|
||||
Normals[i] = vb1->Normal.ToFloat3() * 2.0f - 1.0f;
|
||||
Tangents[i] = vb1->Tangent.ToFloat3() * 2.0f - 1.0f;
|
||||
|
||||
vb0++;
|
||||
vb1++;
|
||||
}
|
||||
}
|
||||
|
||||
void MeshData::SetIndexBuffer(void* data, uint32 indicesCount)
|
||||
{
|
||||
bool use16BitIndexBuffer = indicesCount <= MAX_uint16;
|
||||
@@ -339,19 +265,6 @@ bool MeshData::Pack2Model(WriteStream* stream) const
|
||||
vb1.Tangent = Float1010102(tangent * 0.5f + 0.5f, static_cast<byte>(bitangentSign < 0 ? 1 : 0));
|
||||
vb1.LightmapUVs = Half2(lightmapUV);
|
||||
stream->WriteBytes(&vb1, sizeof(vb1));
|
||||
|
||||
// Pack TBN matrix into a quaternion
|
||||
/*Quaternion quaternionTBN;
|
||||
bool invertedHandednessTBN;
|
||||
CalculateQuaternionFromTBN(tangent, bitangent, normal, &quaternionTBN, &invertedHandednessTBN);
|
||||
quaternionTBN.Normalize();
|
||||
uint32 packedQuaternionTBN = QuantizeNormalizedQuaternionWithHandedness(quaternionTBN, invertedHandednessTBN);
|
||||
|
||||
Float4 unpackedQuaternionTBN = Float4(quaternionTBN.X, quaternionTBN.Y, quaternionTBN.Z, ((invertedHandednessTBN ? 0.0f : 128.0f) + (127.0f * (quaternionTBN.W * 0.5f + 0.5f))) / 255.0f);
|
||||
|
||||
//lods.WriteUint32(packedQuaternionTBN);
|
||||
//lods.WriteFloat4(unpackedQuaternionTBN);
|
||||
*/
|
||||
}
|
||||
|
||||
// Vertex Buffer 2
|
||||
|
||||
@@ -149,22 +149,6 @@ public:
|
||||
/// <param name="verticesCount">Amount of vertices</param>
|
||||
void InitFromModelVertices(ModelVertex19* vertices, uint32 verticesCount);
|
||||
|
||||
/// <summary>
|
||||
/// Init from model vertices array
|
||||
/// [Deprecated on 28.04.2023, expires on 01.01.2024]
|
||||
/// </summary>
|
||||
/// <param name="vertices">Array of vertices</param>
|
||||
/// <param name="verticesCount">Amount of vertices</param>
|
||||
void InitFromModelVertices(ModelVertex18* vertices, uint32 verticesCount);
|
||||
|
||||
/// <summary>
|
||||
/// Init from model vertices array
|
||||
/// [Deprecated on 28.04.2023, expires on 01.01.2024]
|
||||
/// </summary>
|
||||
/// <param name="vertices">Array of vertices</param>
|
||||
/// <param name="verticesCount">Amount of vertices</param>
|
||||
void InitFromModelVertices(ModelVertex15* vertices, uint32 verticesCount);
|
||||
|
||||
/// <summary>
|
||||
/// Init from model vertices array
|
||||
/// </summary>
|
||||
@@ -182,15 +166,6 @@ public:
|
||||
/// <param name="verticesCount">Amount of vertices</param>
|
||||
void InitFromModelVertices(VB0ElementType18* vb0, VB1ElementType18* vb1, VB2ElementType18* vb2, uint32 verticesCount);
|
||||
|
||||
/// <summary>
|
||||
/// Init from model vertices array
|
||||
/// [Deprecated on 28.04.2023, expires on 01.01.2024]
|
||||
/// </summary>
|
||||
/// <param name="vb0">Array of data for vertex buffer 0</param>
|
||||
/// <param name="vb1">Array of data for vertex buffer 1</param>
|
||||
/// <param name="verticesCount">Amount of vertices</param>
|
||||
void InitFromModelVertices(VB0ElementType15* vb0, VB1ElementType15* vb1, uint32 verticesCount);
|
||||
|
||||
/// <summary>
|
||||
/// Sets the index buffer data.
|
||||
/// </summary>
|
||||
|
||||
@@ -70,25 +70,6 @@ enum class MeshBufferType
|
||||
};
|
||||
|
||||
// Vertex structure for all models (versioned)
|
||||
// [Deprecated on 28.04.2023, expires on 01.01.2024]
|
||||
PACK_STRUCT(struct ModelVertex15
|
||||
{
|
||||
Float3 Position;
|
||||
Half2 TexCoord;
|
||||
Float1010102 Normal;
|
||||
Float1010102 Tangent;
|
||||
});
|
||||
|
||||
// [Deprecated on 28.04.2023, expires on 01.01.2024]
|
||||
PACK_STRUCT(struct ModelVertex18
|
||||
{
|
||||
Float3 Position;
|
||||
Half2 TexCoord;
|
||||
Float1010102 Normal;
|
||||
Float1010102 Tangent;
|
||||
Half2 LightmapUVs;
|
||||
});
|
||||
|
||||
// [Deprecated in v1.10]
|
||||
PACK_STRUCT(struct ModelVertex19
|
||||
{
|
||||
@@ -116,19 +97,6 @@ struct RawModelVertex
|
||||
};
|
||||
|
||||
// For vertex data we use three buffers: one with positions, one with other attributes, and one with colors
|
||||
// [Deprecated on 28.04.2023, expires on 01.01.2024]
|
||||
PACK_STRUCT(struct VB0ElementType15
|
||||
{
|
||||
Float3 Position;
|
||||
});
|
||||
// [Deprecated on 28.04.2023, expires on 01.01.2024]
|
||||
PACK_STRUCT(struct VB1ElementType15
|
||||
{
|
||||
Half2 TexCoord;
|
||||
Float1010102 Normal;
|
||||
Float1010102 Tangent;
|
||||
});
|
||||
|
||||
// [Deprecated in v1.10]
|
||||
PACK_STRUCT(struct VB0ElementType18
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user