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

Framework for scaffold geometry optimization - second method #249

Merged
merged 5 commits into from
Oct 24, 2024
Merged
Show file tree
Hide file tree
Changes from 4 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
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace CadRevealFbxProvider.Tests.BatchUtils;
using CadRevealComposer;
using CadRevealComposer.Primitives;
using CadRevealComposer.Tessellation;
using CadRevealFbxProvider.BatchUtils;
using CadRevealFbxProvider.BatchUtils.ScaffoldOptimizer;

public class GeometryOptimizerTests
{
Expand Down
555 changes: 438 additions & 117 deletions CadRevealFbxProvider.Tests/BatchUtils/ScaffoldOptimizerTests.cs

Large diffs are not rendered by default.

This file was deleted.

This file was deleted.

This file was deleted.

117 changes: 0 additions & 117 deletions CadRevealFbxProvider/BatchUtils/ScaffoldOptimizer.cs

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
namespace CadRevealFbxProvider.BatchUtils;
namespace CadRevealFbxProvider.BatchUtils.ScaffoldOptimizer;

using CadRevealComposer;
using CadRevealComposer.Primitives;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace CadRevealFbxProvider.BatchUtils.ScaffoldOptimizer;

using CadRevealComposer.Primitives;

public interface IScaffoldOptimizerResult
{
public APrimitive Get();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
namespace CadRevealFbxProvider.BatchUtils.ScaffoldOptimizer;

using CadRevealComposer.Primitives;
using CadRevealComposer.Tessellation;

public class ScaffoldOptimizer : ScaffoldOptimizerBase
{
protected override List<ScaffoldOptimizerResult>? OptimizeNode(
string nodeName,
Mesh?[] meshes,
APrimitive[] nodeGeometries,
Func<ulong, int, ulong> requestChildMeshInstanceId
)
{
//
// The meshes variable contains all meshes from a single node. It has the same length as nodeGeometries and will
// contain null if the primitive did not contain a mesh. nodeGeometries contains all primitives of the node
// to be optimized, also the non-mesh ones. To optimize meshes,
// 1) select an appropriate set of trigger keywords from the scaffold part names using the string.ContainsAny()
// extension method,
// 2) perform the optimization, which includes using meshes and nodeGeometries as basis for creating a
// completely new combination of InstancedMesh, TriangleMesh, and available non-mesh primitives. It
// is also possible to keep meshes or nodePrimitives the same by passing them on into the new
// combination.
// 3) Add everything in the combination into the results list through ScaffoldOptimizerResult entries,
// which can take InstancesMesh, TriangleMesh, or non-mesh primitives as input.
//

var results = new List<ScaffoldOptimizerResult>();
if (nodeName.ContainsAny(["WordA", "WordB"]))
{
// :TODO: Example if to be removed after the first optimization has been implemented!
}
else if (nodeName.ContainsAny(["WordC", "WordD"]))
{
// :TODO: Example if to be removed after the first optimization has been implemented!
}
else
{
return null;
}

return results;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
namespace CadRevealFbxProvider.BatchUtils.ScaffoldOptimizer;

using System.Drawing;
using System.Linq;
using CadRevealComposer;
using CadRevealComposer.Primitives;
using CadRevealComposer.Tessellation;

static class ScaffoldOptimizerExtensions
{
public static bool ContainsAny(this string str, string[] keywordList) => keywordList.Any(str.Contains);
}

public class ScaffoldOptimizerBase
{
private static Mesh?[] ExtractMeshes(APrimitive[] primitives)
{
var meshes = new List<Mesh?>();
foreach (APrimitive primitive in primitives)
{
Mesh? mesh = primitive switch
{
InstancedMesh instancedMesh => instancedMesh.TemplateMesh,
TriangleMesh triangleMesh => triangleMesh.Mesh,
_ => null
};

meshes.Add(mesh);
}

return meshes.ToArray();
}

public void OptimizeNodes(List<CadRevealNode> nodes, Func<ulong> requestNewInstanceId)
{
foreach (CadRevealNode node in nodes)
{
OptimizeNode(node, requestNewInstanceId);
}
GeometryInstancer.Invoke(nodes);
}

public void OptimizeNode(CadRevealNode node, Func<ulong> requestNewInstanceId)
{
Mesh?[] meshes = ExtractMeshes(node.Geometries);
if (meshes.All(u => u == null))
{
// If we do not find any meshes in the primitive, then we have nothing to optimize and should not update the node primitives
return;
}

var results = OptimizeNode(node.Name, meshes, node.Geometries, RequestChildMeshInstanceId);
if (results == null)
{
// If we do not have a result from the optimization, then we have not optimized anything and should not update the node primitives
return;
}

var primitiveList = new List<APrimitive>();
primitiveList.AddRange(results.Select(result => result.Get()));
node.Geometries = primitiveList.ToArray();

return;
ulong RequestChildMeshInstanceId(ulong instanceIdParentMesh, int indexChildMesh) =>
OnRequestChildMeshInstanceId(instanceIdParentMesh, indexChildMesh, requestNewInstanceId);
}

protected virtual List<ScaffoldOptimizerResult>? OptimizeNode(
string nodeName,
Mesh?[] meshes,
APrimitive[] nodeGeometries,
Func<ulong, int, ulong> requestChildMeshInstanceId
)
{
throw new NotImplementedException();
}

private ulong OnRequestChildMeshInstanceId(
ulong instanceIdParentMesh,
int indexChildMesh,
Func<ulong> requestNewInstanceId
)
{
if (_childMeshInstanceIdLookup.TryGetValue(instanceIdParentMesh, out Dictionary<int, ulong>? retInstanceIdDict))
{
if (retInstanceIdDict.TryGetValue(indexChildMesh, out ulong retInstanceId))
{
return retInstanceId;
}

_childMeshInstanceIdLookup[instanceIdParentMesh].Add(indexChildMesh, requestNewInstanceId());
return _childMeshInstanceIdLookup[instanceIdParentMesh][indexChildMesh];
}

_childMeshInstanceIdLookup.Add(instanceIdParentMesh, new Dictionary<int, ulong>());
_childMeshInstanceIdLookup[instanceIdParentMesh].Add(indexChildMesh, requestNewInstanceId());
return _childMeshInstanceIdLookup[instanceIdParentMesh][indexChildMesh];
}

private readonly Dictionary<ulong, Dictionary<int, ulong>> _childMeshInstanceIdLookup = new();
}
Loading
Loading