diff --git a/Core/Tera/Core.h b/Core/Tera/Core.h index a6f135a..cf59fb9 100644 --- a/Core/Tera/Core.h +++ b/Core/Tera/Core.h @@ -65,6 +65,8 @@ static const unsigned int BUILD_NUMBER = ( // GPU buffer has lower quality due to packed positions and half precision UVs, // so its better to use CPU buffer instead. (Tera uses GPU buffer to render models) #define USE_GPU_VERTEX_BUFFER 0 +// Build and save SkelMesh's raw points index buffers +#define SAVE_RAWINDICES 0 #if _DEBUG // DUMP_PATH should be set in the ENV diff --git a/Core/Tera/USkeletalMesh.cpp b/Core/Tera/USkeletalMesh.cpp index 4323f11..b74dd71 100644 --- a/Core/Tera/USkeletalMesh.cpp +++ b/Core/Tera/USkeletalMesh.cpp @@ -423,20 +423,49 @@ void FStaticLODModel::Serialize(FStream& s, UObject* owner, int32 idx) s << RequiredBones; +#if SAVE_RAWINDICES if (s.GetFV() == VER_TERA_CLASSIC) { + if (!s.IsReading() && RawPointIndices.GetElementCount()) + { + LegacyRawPointIndices.Realloc(RawPointIndices.GetElementCount()); + uint16* dst = (uint16*)LegacyRawPointIndices.GetAllocation(); + uint32* src = (uint32*)RawPointIndices.GetAllocation(); + for (int32 idx = 0; idx < RawPointIndices.GetElementCount(); ++idx) + { + memcpy(&dst[idx], &src[idx], LegacyRawPointIndices.GetElementSize()); + } + } LegacyRawPointIndices.Serialize(s, owner); - RawPointIndices.Realloc(LegacyRawPointIndices.GetElementCount()); - for (int32 idx = 0; idx < LegacyRawPointIndices.GetElementCount(); ++idx) + if (s.IsReading()) { - int32 v = *(uint16*)LegacyRawPointIndices.GetAllocation() + (idx * LegacyRawPointIndices.GetElementSize()); - memcpy((uint8*)RawPointIndices.GetAllocation() + (idx * RawPointIndices.GetElementSize()), &v, RawPointIndices.GetElementSize()); + RawPointIndices.Realloc(LegacyRawPointIndices.GetElementCount()); + uint32* dst = (uint32*)RawPointIndices.GetAllocation(); + uint16* src = (uint16*)LegacyRawPointIndices.GetAllocation(); + for (int32 idx = 0; idx < RawPointIndices.GetElementCount(); ++idx) + { + uint32 item = (uint32)src[idx]; + memcpy(&dst[idx], &item, RawPointIndices.GetElementSize()); + } } } else { RawPointIndices.Serialize(s, owner); } +#else + // Raw point indices are useless. Save disk space by discarding them. + if (s.GetFV() == VER_TERA_CLASSIC) + { + FWordBulkData tmp; + tmp.Serialize(s, owner); + } + else + { + FIntBulkData tmp; + tmp.Serialize(s, owner); + } +#endif if (s.GetFV() > VER_TERA_CLASSIC) { @@ -554,6 +583,15 @@ void FGPUSkinVertexBase::Serialize(FStream& s) } } +void FGPUSkinVertexBase::Serialize(FStream& s, FVector& pos) +{ + if (s.GetFV() == VER_TERA_CLASSIC) + { + s << pos; + } + Serialize(s); +} + bool USkeletalMesh::RegisterProperty(FPropertyTag* property) { if (PROP_IS(property, bHasVertexColors)) @@ -1191,6 +1229,15 @@ bool USkeletalMesh::AcceptVisitor(MeshTravallerData* importData, uint32 lodIdx, delete sectionIndexBufferArray[sectionIndex]; } +#if SAVE_RAWINDICES + lod.RawPointIndices.Realloc(rawPointIndices.size()); + memcpy(lod.RawPointIndices.GetAllocation(), &rawPointIndices.front(), lod.RawPointIndices.GetElementCount()* lod.RawPointIndices.GetElementSize()); +#endif + + if (GetPackage()->GetFileVersion() == VER_TERA_CLASSIC) + { + lod.VertexBufferGPUSkin.bUsePackedPosition = false; + } lod.VertexBufferGPUSkin.ElementCount = lod.NumVertices; lod.VertexBufferGPUSkin.AllocateBuffer(); @@ -1211,6 +1258,10 @@ bool USkeletalMesh::AcceptVisitor(MeshTravallerData* importData, uint32 lodIdx, { // Old skeleton may not match the new one, thus all LODs are invalid. Remove them. LodModels.resize(1); + if (LODInfo) + { + LODInfo->resize(1); + } lodIdx = 0; } diff --git a/Core/Tera/USkeletalMesh.h b/Core/Tera/USkeletalMesh.h index 6224b2a..ca463e1 100644 --- a/Core/Tera/USkeletalMesh.h +++ b/Core/Tera/USkeletalMesh.h @@ -207,6 +207,7 @@ struct FGPUSkinVertexBase { uint8 BoneWeight[MAX_INFLUENCES]; void Serialize(FStream& s); + void Serialize(FStream& s, FVector& pos); }; template @@ -216,9 +217,15 @@ struct FGPUSkinVertexFloatAABB : public FGPUSkinVertexBase { friend FStream& operator<<(FStream& s, FGPUSkinVertexFloatAABB& v) { - v.Serialize(s); - - s << v.Position; + if (s.GetFV() == VER_TERA_CLASSIC) + { + v.Serialize(s, v.Position); + } + else + { + v.Serialize(s); + s << v.Position; + } for (int32 idx = 0; idx < NumTexCoords; ++idx) { @@ -236,8 +243,10 @@ struct FGPUSkinVertexFloatAAB : public FGPUSkinVertexBase { friend FStream& operator<<(FStream& s, FGPUSkinVertexFloatAAB& v) { v.Serialize(s); - - s << v.Position; + if (s.GetFV() > VER_TERA_CLASSIC) + { + s << v.Position; + } for (int32 idx = 0; idx < NumTexCoords; ++idx) { @@ -254,9 +263,15 @@ struct FGPUSkinVertexFloatABB : public FGPUSkinVertexBase { friend FStream& operator<<(FStream& s, FGPUSkinVertexFloatABB& v) { - v.Serialize(s); - - s << v.Position; + if (s.GetFV() == VER_TERA_CLASSIC) + { + v.Serialize(s, v.Position); + } + else + { + v.Serialize(s); + s << v.Position; + } for (int32 idx = 0; idx < NumTexCoords; ++idx) { @@ -274,8 +289,10 @@ struct FGPUSkinVertexFloatAB : public FGPUSkinVertexBase { friend FStream& operator<<(FStream& s, FGPUSkinVertexFloatAB& v) { v.Serialize(s); - - s << v.Position; + if (s.GetFV() > VER_TERA_CLASSIC) + { + s << v.Position; + } for (int32 idx = 0; idx < NumTexCoords; ++idx) { @@ -327,7 +344,7 @@ struct FSkeletalMeshVertexBuffer { bool bDisableCompression = false; bool bUseFullPrecisionUVs = false; - bool bUsePackedPosition = true; + bool bUsePackedPosition = true; // 32-bit client does NOT support packed positions! uint32 NumVertices = 0; uint32 NumTexCoords = 1; diff --git a/Core/Utils/FbxUtils.cpp b/Core/Utils/FbxUtils.cpp index 30a5fb5..08e00b2 100644 --- a/Core/Utils/FbxUtils.cpp +++ b/Core/Utils/FbxUtils.cpp @@ -1838,7 +1838,7 @@ bool FbxUtils::ExportSkeletalMesh(USkeletalMesh* sourceMesh, MeshExportContext& { for (int influenceIndex = 0; influenceIndex < MAX_INFLUENCES; influenceIndex++) { - uint16 influenceBone = v.BoneMap->at(v.InfluenceBones[influenceIndex]); + uint16 influenceBone = v.BoneMap ? v.BoneMap->at(v.InfluenceBones[influenceIndex]) : v.InfluenceBones[influenceIndex]; float w = (float)v.InfluenceWeights[influenceIndex]; float influenceWeight = w / 255.0f;