Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Editor/Tools/LightmapTransferTool.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2621,6 +2621,7 @@ bool TryBuildSidecarEntry(MeshEntry entry, Mesh resultMesh, out MeshUv2Entry sid
return false;

var positions = sidecarMesh.vertices;
var colors = sidecarMesh.colors32;
var uv0List = new List<Vector2>();
(entry.originalMesh ?? resultMesh).GetUVs(0, uv0List);

Expand All @@ -2637,6 +2638,7 @@ bool TryBuildSidecarEntry(MeshEntry entry, Mesh resultMesh, out MeshUv2Entry sid
edgeWelded = entry.wasEdgeWelded,
vertPositions = positions,
vertUv0 = uv0List.ToArray(),
optimizedColors = colors.Length == sidecarMesh.vertexCount ? colors : null,
schemaVersion = Uv2DataAsset.CurrentSchemaVersion,
toolVersion = Uv2DataAsset.ToolVersionStr,
sourceFingerprint = fp,
Expand Down
14 changes: 10 additions & 4 deletions Editor/Uv2AssetPostprocessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -723,7 +723,7 @@ static bool ReplayOptimization(Mesh mesh, MeshUv2Entry entry, bool stale = false
// ── Build optimized arrays via remap ──
// If ground-truth vertex data is available, use it DIRECTLY for positions/normals/tangents.
// This completely bypasses the remap for geometry, eliminating all remap-related vertex errors.
// The remap is only used for UV channels and colors (which aren't stored in ground truth).
// The remap is only used for UV channels and as a fallback for legacy color data.
bool hasGroundTruth = entry.optimizedPositions != null && entry.optimizedPositions.Length == optCount;

var optPos = new Vector3[optCount];
Expand All @@ -750,13 +750,19 @@ static bool ReplayOptimization(Mesh mesh, MeshUv2Entry entry, bool stale = false
System.Array.Copy(entry.optimizedNormals, optNormals, optCount);
if (optTangents != null && entry.optimizedTangents != null && entry.optimizedTangents.Length == optCount)
System.Array.Copy(entry.optimizedTangents, optTangents, optCount);

// UV channels, colors — from remap (UV0 is modified by weld, must come from raw FBX)
if (optColors != null && entry.optimizedColors != null && entry.optimizedColors.Length == optCount)
System.Array.Copy(entry.optimizedColors, optColors, optCount);

// UV channels and legacy colors — from remap (UV0 is modified by weld,
// so it must come from the raw FBX). Optimized colors remain authoritative
// because merged and orphan vertices cannot always be reconstructed by remap.
bool remapColors = optColors != null &&
(entry.optimizedColors == null || entry.optimizedColors.Length != optCount);
for (int i = 0; i < rawCount; i++)
{
int dst = remap[i];
if (dst < 0) continue;
if (optColors != null) optColors[dst] = rawColors[i];
if (remapColors) optColors[dst] = rawColors[i];
for (int ch = 0; ch < 8; ch++)
{
if (ch == 1 || optUvs[ch] == null) continue;
Expand Down
3 changes: 3 additions & 0 deletions Editor/Uv2DataAsset.cs
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ public class MeshUv2Entry
public Vector3[] optimizedNormals;
/// <summary>All vertex tangents from the optimized mesh at Apply time.</summary>
public Vector4[] optimizedTangents;
/// <summary>All vertex colors from the optimized mesh at Apply time.</summary>
public Color32[] optimizedColors;

// ── Shell descriptors (v0.14.0+) ──
/// <summary>Stable shell descriptors for the target mesh UV0 shells.</summary>
Expand Down Expand Up @@ -418,6 +420,7 @@ static void CopyEntryFields(MeshUv2Entry src, MeshUv2Entry dst)
dst.optimizedPositions = src.optimizedPositions;
dst.optimizedNormals = src.optimizedNormals;
dst.optimizedTangents = src.optimizedTangents;
dst.optimizedColors = src.optimizedColors;
dst.shellDescriptors = src.shellDescriptors;
dst.vertexToSourceShellDescriptor = src.vertexToSourceShellDescriptor;
dst.targetShellToSourceShellDescriptor = src.targetShellToSourceShellDescriptor;
Expand Down
Loading