Remove deprecated asset data upgrades and old model vertex structures

This commit is contained in:
Wojtek Figat
2024-12-20 00:48:01 +01:00
parent 1bf29c042b
commit 9f648caac8
14 changed files with 18 additions and 3168 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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>

View File

@@ -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
{