Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Share MeshInfo2 globally #421

Merged
merged 7 commits into from
Sep 6, 2023
Merged
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
1 change: 1 addition & 0 deletions CHANGELOG-PRERELEASE.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ The format is based on [Keep a Changelog].
### Added

### Changed
- Performance: Share MeshInfo2 between SkinnedMesh processing and MergeBone `#421`

### Deprecated

Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ The format is based on [Keep a Changelog].
### Changed
- Improved 'Remove Unused Objects' `#401`
- Remove Unused Objects now removes unnecessary Components & Bones!
- Performance: Share MeshInfo2 between SkinnedMesh processing and MergeBone `#421`

### Deprecated

Expand Down
1 change: 1 addition & 0 deletions Editor/OptimizerProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -165,6 +165,7 @@ private static void DoProcessObject(OptimizerSession session)
new Processors.EditSkinnedMeshComponentProcessor().Process(session);
new Processors.MergeBoneProcessor().Process(session);
new Processors.MakeChildrenProcessor(early: false).Process(session);
session.SaveMeshInfo2();

new Processors.ApplyObjectMapping().Apply(session);
traceAndOptimize.ProcessLater(session);
Expand Down
8 changes: 8 additions & 0 deletions Editor/OptimizerSession.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Anatawa12.AvatarOptimizer.Processors;
using UnityEditor;
using UnityEngine;
using Object = UnityEngine.Object;
Expand All @@ -14,6 +15,7 @@ internal class OptimizerSession
private readonly DummyObject _assetFileObject;
public bool IsTest { get; }
public ObjectMappingBuilder MappingBuilder { get; }
public MeshInfo2Holder MeshInfo2Holder { get; private set; } = new MeshInfo2Holder();

public OptimizerSession(GameObject rootObject, bool addToAsset, bool isTest) :
this(rootObject, addToAsset ? Utils.CreateAssetFile() : null, isTest)
Expand Down Expand Up @@ -69,5 +71,11 @@ public string RelativePath(Transform child)
return Utils.RelativePath(_rootObject.transform, child) ??
throw new ArgumentException("child is not child of rootObject", nameof(child));
}

public void SaveMeshInfo2()
{
MeshInfo2Holder.SaveToMesh(this);
MeshInfo2Holder = null;
}
}
}
59 changes: 2 additions & 57 deletions Editor/Processors/EditSkinnedMeshComponentProcessor.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
using System.Collections.Generic;
using System.Linq;
using Anatawa12.AvatarOptimizer.ErrorReporting;
using Anatawa12.AvatarOptimizer.Processors.SkinnedMeshes;
using UnityEngine;

namespace Anatawa12.AvatarOptimizer.Processors
Expand All @@ -14,74 +11,22 @@ public void Process(OptimizerSession session)
foreach (var component in session.GetComponents<EditSkinnedMeshComponent>())
graph.AddComponent(component);

var holder = new MeshInfo2Holder();

var renderers = session.GetComponents<SkinnedMeshRenderer>();
var processorLists = graph.GetSortedProcessors(renderers);
foreach (var processors in processorLists)
{
var target = holder.GetMeshInfoFor(processors.Target);
var target = session.MeshInfo2Holder.GetMeshInfoFor(processors.Target);

foreach (var processor in processors.GetSorted())
{
// TODO
BuildReport.ReportingObject(processor.Component, () => processor.Process(session, target, holder));
BuildReport.ReportingObject(processor.Component, () => processor.Process(session, target));
target.AssertInvariantContract(
$"after {processor.GetType().Name} " +
$"for {processor.Target.gameObject.name}");
Object.DestroyImmediate(processor.Component);
}
}

holder.SaveToMesh(session);
}
}

internal class MeshInfo2Holder
{
private readonly Dictionary<SkinnedMeshRenderer, MeshInfo2> _skinnedCache =
new Dictionary<SkinnedMeshRenderer, MeshInfo2>();

private readonly Dictionary<MeshRenderer, MeshInfo2> _staticCache = new Dictionary<MeshRenderer, MeshInfo2>();

public MeshInfo2 GetMeshInfoFor(SkinnedMeshRenderer renderer) =>
_skinnedCache.TryGetValue(renderer, out var cached)
? cached
: _skinnedCache[renderer] = new MeshInfo2(renderer);


public MeshInfo2 GetMeshInfoFor(MeshRenderer renderer) =>
_staticCache.TryGetValue(renderer, out var cached)
? cached
: _staticCache[renderer] = new MeshInfo2(renderer);

public void SaveToMesh(OptimizerSession session)
{
foreach (var keyValuePair in _skinnedCache)
{
var targetRenderer = keyValuePair.Key;
if (!targetRenderer) continue;

keyValuePair.Value.WriteToSkinnedMeshRenderer(targetRenderer, session);
}

foreach (var keyValuePair in _staticCache)
{
var targetRenderer = keyValuePair.Key;
if (!targetRenderer) continue;
var meshInfo = keyValuePair.Value;
var meshFilter = targetRenderer.GetComponent<MeshFilter>();

BuildReport.ReportingObject(targetRenderer, () =>
{
var mesh = meshFilter.sharedMesh
? session.MayCreate(meshFilter.sharedMesh)
: session.AddToAsset(new Mesh());
meshInfo.WriteToMesh(mesh);
meshFilter.sharedMesh = mesh;
targetRenderer.sharedMaterials = meshInfo.SubMeshes.Select(x => x.SharedMaterial).ToArray();
});
}
}
}
}
11 changes: 4 additions & 7 deletions Editor/Processors/MergeBoneProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,9 @@ public void Process(OptimizerSession session)

BuildReport.ReportingObjects(session.GetComponents<SkinnedMeshRenderer>(), renderer =>
{
if (renderer.bones.Where(x => x).Any(mergeMapping.ContainsKey))
DoBoneMap2(session, renderer, mergeMapping);
var meshInfo2 = session.MeshInfo2Holder.GetMeshInfoFor(renderer);
if (meshInfo2.Bones.Any(x => x.Transform && mergeMapping.ContainsKey(x.Transform)))
DoBoneMap2(meshInfo2, mergeMapping);
});

foreach (var pair in mergeMapping)
Expand All @@ -42,10 +43,8 @@ public void Process(OptimizerSession session)
Object.DestroyImmediate(pair.gameObject);
}

private void DoBoneMap2(OptimizerSession session, SkinnedMeshRenderer renderer,
Dictionary<Transform, Transform> mergeMapping)
private void DoBoneMap2(MeshInfo2 meshInfo2, Dictionary<Transform, Transform> mergeMapping)
{
var meshInfo2 = new MeshInfo2(renderer);
var primaryBones = new Dictionary<Transform, Bone>();
var boneReplaced = false;

Expand Down Expand Up @@ -138,8 +137,6 @@ private void DoBoneMap2(OptimizerSession session, SkinnedMeshRenderer renderer,
.Select(g => (g.Key, g.Sum(x => x.weight)))
.ToList();
}

meshInfo2.WriteToSkinnedMeshRenderer(renderer, session);
}

private readonly struct BoneUniqKey : IEquatable<BoneUniqKey>
Expand Down
56 changes: 56 additions & 0 deletions Editor/Processors/MeshInfo2Holder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System.Collections.Generic;
using System.Linq;
using Anatawa12.AvatarOptimizer.ErrorReporting;
using Anatawa12.AvatarOptimizer.Processors.SkinnedMeshes;
using UnityEngine;

namespace Anatawa12.AvatarOptimizer.Processors
{
internal class MeshInfo2Holder
{
private readonly Dictionary<SkinnedMeshRenderer, MeshInfo2> _skinnedCache =
new Dictionary<SkinnedMeshRenderer, MeshInfo2>();

private readonly Dictionary<MeshRenderer, MeshInfo2> _staticCache = new Dictionary<MeshRenderer, MeshInfo2>();

public MeshInfo2 GetMeshInfoFor(SkinnedMeshRenderer renderer) =>
_skinnedCache.TryGetValue(renderer, out var cached)
? cached
: _skinnedCache[renderer] = new MeshInfo2(renderer);


public MeshInfo2 GetMeshInfoFor(MeshRenderer renderer) =>
_staticCache.TryGetValue(renderer, out var cached)
? cached
: _staticCache[renderer] = new MeshInfo2(renderer);

public void SaveToMesh(OptimizerSession session)
{
foreach (var keyValuePair in _skinnedCache)
{
var targetRenderer = keyValuePair.Key;
if (!targetRenderer) continue;

keyValuePair.Value.WriteToSkinnedMeshRenderer(targetRenderer, session);
}

foreach (var keyValuePair in _staticCache)
{
var targetRenderer = keyValuePair.Key;
if (!targetRenderer) continue;
var meshInfo = keyValuePair.Value;
var meshFilter = targetRenderer.GetComponent<MeshFilter>();

BuildReport.ReportingObject(targetRenderer, () =>
{
var mesh = meshFilter.sharedMesh
? session.MayCreate(meshFilter.sharedMesh)
: session.AddToAsset(new Mesh());
meshInfo.WriteToMesh(mesh);
meshFilter.sharedMesh = mesh;
targetRenderer.sharedMaterials = meshInfo.SubMeshes.Select(x => x.SharedMaterial).ToArray();
});
}
}
}
}
3 changes: 3 additions & 0 deletions Editor/Processors/MeshInfo2Holder.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions Editor/Processors/SkinnedMeshes/EditSkinnedMeshProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ protected EditSkinnedMeshProcessor(TComponent component)
Target = component.GetComponent<SkinnedMeshRenderer>();
}

public abstract void Process(OptimizerSession session, MeshInfo2 target, MeshInfo2Holder meshInfo2Holder);
public abstract void Process(OptimizerSession session, MeshInfo2 target);

public abstract IMeshInfoComputer GetComputer(IMeshInfoComputer upstream);

Expand All @@ -42,7 +42,7 @@ internal interface IEditSkinnedMeshProcessor
IEnumerable<SkinnedMeshRenderer> Dependencies { get; }
SkinnedMeshRenderer Target { get; }
EditSkinnedMeshComponent Component { get; }
void Process(OptimizerSession session, MeshInfo2 target, MeshInfo2Holder meshInfo2Holder);
void Process(OptimizerSession session, MeshInfo2 target);

[NotNull] IMeshInfoComputer GetComputer([NotNull] IMeshInfoComputer upstream);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public FreezeBlendShapeProcessor(FreezeBlendShape component) : base(component)

public override EditSkinnedMeshProcessorOrder ProcessOrder => EditSkinnedMeshProcessorOrder.AfterRemoveMesh;

public override void Process(OptimizerSession session, MeshInfo2 target, MeshInfo2Holder meshInfo2Holder)
public override void Process(OptimizerSession session, MeshInfo2 target)
{
FreezeBlendShapes(Target, session, target, Component.FreezingShapeKeys);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public InternalAutoFreezeMeaninglessBlendShapeProcessor(InternalAutoFreezeMeanin

public override EditSkinnedMeshProcessorOrder ProcessOrder => EditSkinnedMeshProcessorOrder.AutoConfigureFreezeBlendShape;

public override void Process(OptimizerSession session, MeshInfo2 target, MeshInfo2Holder meshInfo2Holder)
public override void Process(OptimizerSession session, MeshInfo2 target)
{
var meaningfulBlendShapes = new HashSet<string>();

Expand Down
6 changes: 3 additions & 3 deletions Editor/Processors/SkinnedMeshes/MergeSkinnedMeshProcessor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@ public MergeSkinnedMeshProcessor(MergeSkinnedMesh component) : base(component)

public override EditSkinnedMeshProcessorOrder ProcessOrder => EditSkinnedMeshProcessorOrder.Generation;

public override void Process(OptimizerSession session, MeshInfo2 target, MeshInfo2Holder meshInfo2Holder)
public override void Process(OptimizerSession session, MeshInfo2 target)
{
var meshInfos = Component.renderersSet.GetAsList().Select(meshInfo2Holder.GetMeshInfoFor)
.Concat(Component.staticRenderersSet.GetAsList().Select(meshInfo2Holder.GetMeshInfoFor))
var meshInfos = Component.renderersSet.GetAsList().Select(session.MeshInfo2Holder.GetMeshInfoFor)
.Concat(Component.staticRenderersSet.GetAsList().Select(session.MeshInfo2Holder.GetMeshInfoFor))
.ToArray();
var sourceMaterials = meshInfos.Select(x => x.SubMeshes.Select(y => y.SharedMaterial).ToArray()).ToArray();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ public MergeToonLitMaterialProcessor(MergeToonLitMaterial component) : base(comp

public override EditSkinnedMeshProcessorOrder ProcessOrder => EditSkinnedMeshProcessorOrder.AfterRemoveMesh;

public override void Process(OptimizerSession session, MeshInfo2 target, MeshInfo2Holder meshInfo2Holder)
public override void Process(OptimizerSession session, MeshInfo2 target)
{
// compute usages. AdditionalTemporal is usage count for now.
// if #usages is not zero for merging triangles
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public RemoveMeshByBlendShapeProcessor(RemoveMeshByBlendShape component) : base(
// This needs to be less than FreezeBlendshapeProcessor.ProcessOrder.
public override EditSkinnedMeshProcessorOrder ProcessOrder => EditSkinnedMeshProcessorOrder.RemovingMesh;

public override void Process(OptimizerSession session, MeshInfo2 target, MeshInfo2Holder meshInfo2Holder)
public override void Process(OptimizerSession session, MeshInfo2 target)
{
var byBlendShapeVertices = new HashSet<Vertex>();
var sqrTolerance = Component.tolerance * Component.tolerance;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ public RemoveMeshInBoxProcessor(RemoveMeshInBox component) : base(component)

public override EditSkinnedMeshProcessorOrder ProcessOrder => EditSkinnedMeshProcessorOrder.RemovingMesh;

public override void Process(OptimizerSession session, MeshInfo2 target, MeshInfo2Holder meshInfo2Holder)
public override void Process(OptimizerSession session, MeshInfo2 target)
{
var inBoxVertices = new HashSet<Vertex>();
// Vertex.AdditionalTemporal: 0 if in box, 1 if out of box
Expand Down