Skip to content

Commit

Permalink
Merge pull request #421 from anatawa12/global-meshinfo2-holder
Browse files Browse the repository at this point in the history
Share MeshInfo2 globally
  • Loading branch information
anatawa12 authored Sep 6, 2023
2 parents 7824996 + 31b0e73 commit 2ae0024
Show file tree
Hide file tree
Showing 15 changed files with 86 additions and 74 deletions.
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

0 comments on commit 2ae0024

Please sign in to comment.