Making export to STL process the scene

This commit is contained in:
Lars Brubaker 2022-05-09 12:23:11 -07:00
parent 55454a8615
commit 20a100dc70
3 changed files with 4 additions and 252 deletions

View file

@ -84,7 +84,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
null,
(reporter, cancellationTokenSource) =>
{
this.cancellationToken = cancellationTokenSource as CancellationTokenSource;
this.cancellationToken = cancellationTokenSource;
var progressStatus = new ProgressStatus();
reporter.Report(progressStatus);
@ -142,7 +142,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
}
else
{
resultsMesh = CombineParticipanets(reporter, participants, cancellationToken);
resultsMesh = Object3D.CombineParticipanets(SourceContainer, participants, cancellationToken, reporter);
}
var resultsItem = new Object3D()
@ -152,7 +152,7 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
if (holes != null)
{
var holesMesh = CombineParticipanets(null, holes, cancellationToken);
var holesMesh = CombineParticipanets(SourceContainer, holes, cancellationToken, null);
if (holesMesh != null)
{
var holesItem = new Object3D()
@ -185,149 +185,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
SourceContainer.Visible = false;
}
private Mesh CombineParticipanets(IProgress<ProgressStatus> reporter, IEnumerable<IObject3D> participants, CancellationToken cancellationToken)
{
List<List<(Mesh mesh, Matrix4X4 matrix, AxisAlignedBoundingBox aabb)>> touchingSets = GetTouchingMeshes(participants);
var totalOperations = touchingSets.Sum(t => t.Count);
double amountPerOperation = 1.0 / totalOperations;
double ratioCompleted = 0;
var progressStatus = new ProgressStatus();
var setMeshes = new List<Mesh>();
foreach (var set in touchingSets)
{
var setMesh = set.First().Item1;
var keepWorldMatrix = set.First().matrix;
if (set.Count > 1)
{
#if true
setMesh = BooleanProcessing.DoArray(set.Select(i => (i.mesh, i.matrix)),
CsgModes.Union,
Processing,
InputResolution,
OutputResolution,
reporter,
cancellationToken);
#else
bool first = true;
foreach (var next in set)
{
if (first)
{
first = false;
continue;
}
setMesh = BooleanProcessing.Do(setMesh,
keepWorldMatrix,
// other mesh
next.mesh,
next.matrix,
// operation type
CsgModes.Union,
Processing,
InputResolution,
OutputResolution,
// reporting
reporter,
amountPerOperation,
ratioCompleted,
progressStatus,
cancellationToken);
// after the first time we get a result the results mesh is in the right coordinate space
keepWorldMatrix = Matrix4X4.Identity;
// report our progress
ratioCompleted += amountPerOperation;
progressStatus.Progress0To1 = ratioCompleted;
reporter?.Report(progressStatus);
}
#endif
setMeshes.Add(setMesh);
}
else
{
setMesh.Transform(keepWorldMatrix);
// report our progress
ratioCompleted += amountPerOperation;
progressStatus.Progress0To1 = ratioCompleted;
reporter?.Report(progressStatus);
setMeshes.Add(setMesh);
}
}
Mesh resultsMesh = null;
foreach (var setMesh in setMeshes)
{
if (resultsMesh == null)
{
resultsMesh = setMesh;
}
else
{
resultsMesh.CopyAllFaces(setMesh, Matrix4X4.Identity);
}
}
return resultsMesh;
}
private List<List<(Mesh mesh, Matrix4X4 matrix, AxisAlignedBoundingBox aabb)>> GetTouchingMeshes(IEnumerable<IObject3D> participants)
{
void AddAllTouching(List<(Mesh mesh, Matrix4X4 matrix, AxisAlignedBoundingBox aabb)> touching,
List<(Mesh mesh, Matrix4X4 matrix, AxisAlignedBoundingBox aabb)> available)
{
// add the frirst item
touching.Add(available[available.Count - 1]);
available.RemoveAt(available.Count - 1);
var indexBeingChecked = 0;
// keep adding items until we have checked evry item in the the touching list
while (indexBeingChecked < touching.Count
&& available.Count > 0)
{
// look for a aabb that intersects any aabb in the set
for (int i = available.Count - 1; i >= 0; i--)
{
if (touching[indexBeingChecked].aabb.Intersects(available[i].aabb))
{
touching.Add(available[i]);
available.RemoveAt(i);
}
}
indexBeingChecked++;
}
}
var allItems = participants.Select(i =>
{
var mesh = i.Mesh.Copy(CancellationToken.None);
var matrix = i.WorldMatrix(SourceContainer);
var aabb = mesh.GetAxisAlignedBoundingBox(matrix);
return (mesh, matrix, aabb);
}).ToList();
var touchingSets = new List<List<(Mesh mesh, Matrix4X4 matrix, AxisAlignedBoundingBox aabb)>>();
while (allItems.Count > 0)
{
var touchingSet = new List<(Mesh mesh, Matrix4X4 matrix, AxisAlignedBoundingBox aabb)>();
touchingSets.Add(touchingSet);
AddAllTouching(touchingSet, allItems);
}
return touchingSets;
}
public void UpdateControls(PublicPropertyChange change)
{
change.SetRowVisible(nameof(InputResolution), () => Processing != ProcessingModes.Polygons);

View file

@ -304,111 +304,6 @@ namespace MatterHackers.MatterControl.PartPreviewWindow.View3D
}
}
public static IEnumerable<IObject3D> DoSubtract(IObject3D sourceContainer,
IEnumerable<IObject3D> keepItems,
IEnumerable<IObject3D> removeItems,
IProgress<ProgressStatus> reporter,
CancellationToken cancellationToken,
ProcessingModes processingMode = ProcessingModes.Polygons,
ProcessingResolution inputResolution = ProcessingResolution._64,
ProcessingResolution outputResolution = ProcessingResolution._64)
{
var results = new List<IObject3D>();
if (keepItems?.Any() == true)
{
if (removeItems?.Any() == true)
{
foreach (var keep in keepItems)
{
#if false
var items = removeItems.Select(i => (i.Mesh, i.WorldMatrix(sourceContainer))).ToList();
items.Insert(0, (keep.Mesh, keep.Matrix));
var resultsMesh = BooleanProcessing.DoArray(items,
CsgModes.Subtract,
processingMode,
inputResolution,
outputResolution,
reporter,
cancellationToken);
#else
var totalOperations = removeItems.Count() * keepItems.Count();
double amountPerOperation = 1.0 / totalOperations;
double ratioCompleted = 0;
var progressStatus = new ProgressStatus
{
Status = "Do CSG"
};
var resultsMesh = keep.Mesh;
var keepWorldMatrix = keep.Matrix;
if (sourceContainer != null)
{
keepWorldMatrix = keep.WorldMatrix(sourceContainer);
}
foreach (var remove in removeItems)
{
var removeWorldMatrix = remove.Matrix;
if (sourceContainer != null)
{
removeWorldMatrix = remove.WorldMatrix(sourceContainer);
}
resultsMesh = BooleanProcessing.Do(resultsMesh,
keepWorldMatrix,
// other mesh
remove.Mesh,
removeWorldMatrix,
// operation type
CsgModes.Subtract,
processingMode,
inputResolution,
outputResolution,
// reporting
reporter,
amountPerOperation,
ratioCompleted,
progressStatus,
cancellationToken);
// after the first time we get a result the results mesh is in the right coordinate space
keepWorldMatrix = Matrix4X4.Identity;
// report our progress
ratioCompleted += amountPerOperation;
progressStatus.Progress0To1 = ratioCompleted;
reporter?.Report(progressStatus);
}
#endif
// store our results mesh
var resultsItem = new Object3D()
{
Mesh = resultsMesh,
Visible = false,
OwnerID = keep.ID
};
// copy all the properties but the matrix
if (sourceContainer != null)
{
resultsItem.CopyWorldProperties(keep, sourceContainer, Object3DPropertyFlags.All & (~(Object3DPropertyFlags.Matrix | Object3DPropertyFlags.Visible)));
}
else
{
resultsItem.CopyProperties(keep, Object3DPropertyFlags.All & (~(Object3DPropertyFlags.Matrix | Object3DPropertyFlags.Visible)));
}
// and add it to this
results.Add(resultsItem);
}
}
}
return results;
}
public static void CleanUpSelectedChildrenIDs(OperationSourceContainerObject3D item)
{
if (item is ISelectableChildContainer selectableChildContainer)

@ -1 +1 @@
Subproject commit b426c1d2361ca4ef15bd6a77333a44d610ad127e
Subproject commit 6750bc4daa8c0188b61ebf61bbdeb3ae57b8a998