예제 #1
0
        private void Intersect(CancellationToken cancellationToken, IProgress <ProgressStatus> reporter)
        {
            SourceContainer.Visible = true;
            RemoveAllButSource();

            var participants = SourceContainer.VisibleMeshes();

            if (participants.Count() < 2)
            {
                if (participants.Count() == 1)
                {
                    var newMesh = new Object3D();
                    newMesh.CopyProperties(participants.First(), Object3DPropertyFlags.All);
                    newMesh.Mesh = participants.First().Mesh;
                    this.Children.Add(newMesh);
                    SourceContainer.Visible = false;
                }
                return;
            }

            var first            = participants.First();
            var resultsMesh      = first.Mesh;
            var firstWorldMatrix = first.WorldMatrix(SourceContainer);

            var    totalOperations    = participants.Count() - 1;
            double amountPerOperation = 1.0 / totalOperations;
            double percentCompleted   = 0;

            ProgressStatus progressStatus = new ProgressStatus();

            foreach (var item in participants)
            {
                if (item != first)
                {
                    var itemWorldMatrix = item.WorldMatrix(SourceContainer);
                    resultsMesh = BooleanProcessing.Do(item.Mesh, itemWorldMatrix,
                                                       resultsMesh, firstWorldMatrix,
                                                       2,
                                                       reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken);
                    // after the first union we are working with the transformed mesh and don't need the first transform
                    firstWorldMatrix = Matrix4X4.Identity;

                    percentCompleted           += amountPerOperation;
                    progressStatus.Progress0To1 = percentCompleted;
                    reporter?.Report(progressStatus);
                }
            }

            var resultsItem = new Object3D()
            {
                Mesh = resultsMesh
            };

            resultsItem.CopyProperties(first, Object3DPropertyFlags.All & (~Object3DPropertyFlags.Matrix));
            this.Children.Add(resultsItem);
            SourceContainer.Visible = false;
        }
예제 #2
0
        public void Combine(CancellationToken cancellationToken, IProgress <ProgressStatus> reporter)
        {
            ResetMeshWrapperMeshes(Object3DPropertyFlags.All, cancellationToken);

            var participants = this.Descendants().Where(o => o.OwnerID == this.ID).ToList();

            if (participants.Count() < 2)
            {
                return;
            }

            var first = participants.First();

            var    totalOperations    = participants.Count() - 1;
            double amountPerOperation = 1.0 / totalOperations;
            double ratioCompleted     = 0;

            ProgressStatus progressStatus = new ProgressStatus();

            foreach (var item in participants)
            {
                if (item != first)
                {
                    var result = BooleanProcessing.Do(item.Mesh,
                                                      item.WorldMatrix(),
                                                      first.Mesh,
                                                      first.WorldMatrix(),
                                                      CsgModes.Union,
                                                      ProcessingModes.Polygons,
                                                      ProcessingResolution._64,
                                                      ProcessingResolution._64,
                                                      reporter,
                                                      amountPerOperation,
                                                      ratioCompleted,
                                                      progressStatus,
                                                      cancellationToken);

                    var inverse = first.WorldMatrix();
                    inverse.Invert();
                    result.Transform(inverse);
                    using (first.RebuildLock())
                    {
                        first.Mesh = result;
                    }

                    ratioCompleted += amountPerOperation;
                    progressStatus.Progress0To1 = ratioCompleted;
                    reporter?.Report(progressStatus);
                }
            }
        }
        private void Intersect(CancellationToken cancellationToken, IProgress <ProgressStatus> reporter)
        {
            ResetMeshWrapperMeshes(Object3DPropertyFlags.All, cancellationToken);

            var participants = this.DescendantsAndSelf().Where((obj) => obj.OwnerID == this.ID);

            if (participants.Count() > 1)
            {
                var first = participants.First();

                var    totalOperations    = participants.Count() - 1;
                double amountPerOperation = 1.0 / totalOperations;
                double ratioCompleted     = 0;

                ProgressStatus progressStatus = new ProgressStatus();
                foreach (var remove in participants)
                {
                    if (remove != first)
                    {
                        var result = BooleanProcessing.Do(remove.Mesh,
                                                          remove.WorldMatrix(),
                                                          first.Mesh,
                                                          first.WorldMatrix(),
                                                          CsgModes.Intersect,
                                                          ProcessingModes.Polygons,
                                                          ProcessingResolution._64,
                                                          ProcessingResolution._64,
                                                          reporter,
                                                          amountPerOperation,
                                                          ratioCompleted,
                                                          progressStatus,
                                                          cancellationToken);

                        var inverse = first.WorldMatrix();
                        inverse.Invert();
                        result.Transform(inverse);
                        using (first.RebuildLock())
                        {
                            first.Mesh = result;
                        }
                        remove.Visible = false;

                        ratioCompleted += amountPerOperation;
                        progressStatus.Progress0To1 = ratioCompleted;
                        reporter.Report(progressStatus);
                    }
                }
            }
        }
        public static void Subtract(List <IObject3D> keepObjects, List <IObject3D> removeObjects, CancellationToken cancellationToken, IProgress <ProgressStatus> reporter)
        {
            if (removeObjects.Any() &&
                keepObjects.Any())
            {
                var    totalOperations    = removeObjects.Count * keepObjects.Count;
                double amountPerOperation = 1.0 / totalOperations;
                double percentCompleted   = 0;

                ProgressStatus progressStatus = new ProgressStatus();
                foreach (var remove in removeObjects.Select((r) => (obj3D: r, matrix: r.WorldMatrix())).ToList())
                {
                    foreach (var keep in keepObjects.Select((r) => (obj3D: r, matrix: r.WorldMatrix())).ToList())
                    {
                        progressStatus.Status = "Copy Remove";
                        reporter?.Report(progressStatus);
                        var transformedRemove = remove.obj3D.Mesh.Copy(cancellationToken);
                        transformedRemove.Transform(remove.matrix);

                        progressStatus.Status = "Copy Keep";
                        reporter?.Report(progressStatus);
                        var transformedKeep = keep.obj3D.Mesh.Copy(cancellationToken);
                        transformedKeep.Transform(keep.matrix);

                        progressStatus.Status = "Do CSG";
                        reporter?.Report(progressStatus);
                        var result  = BooleanProcessing.Do(transformedKeep, transformedRemove, 1, reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken);
                        var inverse = keep.matrix.Inverted;
                        result.Transform(inverse);

                        using (keep.obj3D.RebuildLock())
                        {
                            keep.obj3D.Mesh = result;
                        }

                        percentCompleted           += amountPerOperation;
                        progressStatus.Progress0To1 = percentCompleted;
                        reporter?.Report(progressStatus);
                    }

                    remove.obj3D.Visible = false;
                }
            }
        }
예제 #5
0
        private void Combine(CancellationToken cancellationToken, IProgress <ProgressStatus> reporter)
        {
            SourceContainer.Visible = true;
            RemoveAllButSource();

            var participants = SourceContainer.VisibleMeshes();

            if (participants.Count() < 2)
            {
                if (participants.Count() == 1)
                {
                    var newMesh = new Object3D();
                    newMesh.CopyProperties(participants.First(), Object3DPropertyFlags.All);
                    newMesh.Mesh = participants.First().Mesh;
                    this.Children.Add(newMesh);
                    SourceContainer.Visible = false;
                }

                return;
            }

            var items       = participants.Select(i => (i.Mesh, i.WorldMatrix(SourceContainer)));
            var resultsMesh = BooleanProcessing.DoArray(items,
                                                        BooleanProcessing.CsgModes.Union,
                                                        Processing,
                                                        InputResolution,
                                                        OutputResolution,
                                                        reporter,
                                                        cancellationToken);

            var resultsItem = new Object3D()
            {
                Mesh = resultsMesh
            };

            resultsItem.CopyProperties(participants.First(), Object3DPropertyFlags.All & (~Object3DPropertyFlags.Matrix));
            this.Children.Add(resultsItem);
            SourceContainer.Visible = false;
        }
예제 #6
0
        public static void Combine(List <IObject3D> participants, CancellationToken cancellationToken, IProgress <ProgressStatus> reporter)
        {
            var first = participants.First();

            var    totalOperations    = participants.Count() - 1;
            double amountPerOperation = 1.0 / totalOperations;
            double percentCompleted   = 0;

            ProgressStatus progressStatus = new ProgressStatus();

            foreach (var item in participants)
            {
                if (item != first)
                {
                    var transformedRemove = item.Mesh.Copy(CancellationToken.None);
                    transformedRemove.Transform(item.WorldMatrix());

                    var transformedKeep = first.Mesh.Copy(CancellationToken.None);
                    transformedKeep.Transform(first.WorldMatrix());

                    var result = BooleanProcessing.Do(transformedKeep, transformedRemove, 0, reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken);

                    var inverse = first.WorldMatrix();
                    inverse.Invert();
                    result.Transform(inverse);
                    using (first.RebuildLock())
                    {
                        first.Mesh = result;
                    }
                    item.Visible = false;

                    percentCompleted           += amountPerOperation;
                    progressStatus.Progress0To1 = percentCompleted;
                    reporter.Report(progressStatus);
                }
            }
        }
예제 #7
0
        private void SubtractAndReplace(CancellationToken cancellationToken, IProgress <ProgressStatus> reporter)
        {
            SourceContainer.Visible = true;
            RemoveAllButSource();

            var parentOfPaintTargets = SourceContainer.DescendantsAndSelfMultipleChildrenFirstOrSelf();

            if (parentOfPaintTargets.Children.Count() < 2)
            {
                if (parentOfPaintTargets.Children.Count() == 1)
                {
                    this.Children.Add(SourceContainer.Clone());
                    SourceContainer.Visible = false;
                }

                return;
            }

            SubtractObject3D_2.CleanUpSelectedChildrenNames(this);

            var paintObjects = parentOfPaintTargets.Children
                               .Where((i) => SelectedChildren
                                      .Contains(i.ID))
                               .SelectMany(c => c.VisibleMeshes())
                               .ToList();

            var keepItems = parentOfPaintTargets.Children
                            .Where((i) => !SelectedChildren
                                   .Contains(i.ID));

            var keepVisibleItems = keepItems.SelectMany(c => c.VisibleMeshes()).ToList();

            if (paintObjects.Any() &&
                keepVisibleItems.Any())
            {
                var    totalOperations    = paintObjects.Count * keepVisibleItems.Count;
                double amountPerOperation = 1.0 / totalOperations;
                double percentCompleted   = 0;

                var progressStatus = new ProgressStatus
                {
                    Status = "Do CSG"
                };

                foreach (var keep in keepVisibleItems)
                {
                    var keepResultsMesh = keep.Mesh;
                    var keepWorldMatrix = keep.WorldMatrix(SourceContainer);

                    foreach (var paint in paintObjects)
                    {
                        Mesh paintMesh = BooleanProcessing.Do(keepResultsMesh,
                                                              keepWorldMatrix,
                                                              // paint data
                                                              paint.Mesh,
                                                              paint.WorldMatrix(SourceContainer),
                                                              // operation type
                                                              2,
                                                              // reporting data
                                                              reporter,
                                                              amountPerOperation,
                                                              percentCompleted,
                                                              progressStatus,
                                                              cancellationToken);

                        keepResultsMesh = BooleanProcessing.Do(keepResultsMesh,
                                                               keepWorldMatrix,
                                                               // point data
                                                               paint.Mesh,
                                                               paint.WorldMatrix(SourceContainer),
                                                               // operation type
                                                               1,
                                                               // reporting data
                                                               reporter,
                                                               amountPerOperation,
                                                               percentCompleted,
                                                               progressStatus,
                                                               cancellationToken);

                        // after the first time we get a result the results mesh is in the right coordinate space
                        keepWorldMatrix = Matrix4X4.Identity;

                        // store our intersection (paint) results mesh
                        var paintResultsItem = new Object3D()
                        {
                            Mesh    = paintMesh,
                            Visible = false,
                            OwnerID = paint.ID
                        };
                        // copy all the properties but the matrix
                        paintResultsItem.CopyWorldProperties(paint, SourceContainer, Object3DPropertyFlags.All & (~(Object3DPropertyFlags.Matrix | Object3DPropertyFlags.Visible)));
                        // and add it to this
                        this.Children.Add(paintResultsItem);

                        // report our progress
                        percentCompleted           += amountPerOperation;
                        progressStatus.Progress0To1 = percentCompleted;
                        reporter?.Report(progressStatus);
                    }

                    // store our results mesh
                    var keepResultsItem = new Object3D()
                    {
                        Mesh    = keepResultsMesh,
                        Visible = false,
                        OwnerID = keep.ID
                    };
                    // copy all the properties but the matrix
                    keepResultsItem.CopyWorldProperties(keep, SourceContainer, Object3DPropertyFlags.All & (~(Object3DPropertyFlags.Matrix | Object3DPropertyFlags.Visible)));
                    // and add it to this
                    this.Children.Add(keepResultsItem);
                }

                foreach (var child in Children)
                {
                    child.Visible = true;
                }

                SourceContainer.Visible = false;
            }
        }
        private void Rebuild(UndoBuffer undoBuffer)
        {
            var rebuildLock = RebuildLock();

            ResetMeshWrapperMeshes(Object3DPropertyFlags.All, CancellationToken.None);

            ApplicationController.Instance.Tasks.Execute("Intersection".Localize(), (reporter, cancellationToken) =>
            {
                var progressStatus = new ProgressStatus();

                var participants = this.DescendantsAndSelf().Where((obj) => obj.OwnerID == this.ID);

                try
                {
                    if (participants.Count() > 1)
                    {
                        var first = participants.First();

                        var totalOperations       = participants.Count() - 1;
                        double amountPerOperation = 1.0 / totalOperations;
                        double percentCompleted   = 0;

                        foreach (var remove in participants)
                        {
                            if (remove != first)
                            {
                                var transformedRemove = remove.Mesh.Copy(CancellationToken.None);
                                transformedRemove.Transform(remove.WorldMatrix());

                                var transformedKeep = first.Mesh.Copy(CancellationToken.None);
                                transformedKeep.Transform(first.WorldMatrix());

                                var result = BooleanProcessing.Do(transformedKeep, transformedRemove, 2, reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken);

                                var inverse = first.WorldMatrix();
                                inverse.Invert();
                                result.Transform(inverse);
                                using (first.RebuildLock())
                                {
                                    first.Mesh = result;
                                }
                                remove.Visible = false;

                                percentCompleted           += amountPerOperation;
                                progressStatus.Progress0To1 = percentCompleted;
                                reporter.Report(progressStatus);
                            }
                        }
                    }
                }
                catch { }

                UiThread.RunOnIdle(() =>
                {
                    rebuildLock.Dispose();
                    base.Invalidate(new InvalidateArgs(this, InvalidateType.Content));
                });

                return(Task.CompletedTask);
            });
        }
예제 #9
0
        public void Subtract(CancellationToken cancellationToken, IProgress <ProgressStatus> reporter)
        {
            ResetMeshWrapperMeshes(Object3DPropertyFlags.All, cancellationToken);

            bool ItemInSubtractList(IObject3D item)
            {
                if (ItemsToSubtract.Contains(item.ID))
                {
                    return(true);
                }

                // check if the wrapped item is in the subtract list
                if (item.Children.Count > 0 && ItemsToSubtract.Contains(item.Children.First().ID))
                {
                    return(true);
                }

                return(false);
            }

            var removeObjects = this.Children
                                .Where(i => ItemInSubtractList(i))
                                .SelectMany(h => h.DescendantsAndSelf())
                                .Where(c => c.OwnerID == this.ID).ToList();
            var keepObjects = this.Children
                              .Where(i => !ItemInSubtractList(i))
                              .SelectMany(h => h.DescendantsAndSelf())
                              .Where(c => c.OwnerID == this.ID).ToList();

            if (removeObjects.Any() &&
                keepObjects.Any())
            {
                var    totalOperations    = removeObjects.Count * keepObjects.Count;
                double amountPerOperation = 1.0 / totalOperations;
                double percentCompleted   = 0;

                ProgressStatus progressStatus = new ProgressStatus();
                foreach (var remove in removeObjects.Select((r) => (obj3D: r, matrix: r.WorldMatrix())).ToList())
                {
                    foreach (var keep in keepObjects.Select((r) => (obj3D: r, matrix: r.WorldMatrix())).ToList())
                    {
                        progressStatus.Status = "Copy Remove";
                        reporter?.Report(progressStatus);

                        progressStatus.Status = "Copy Keep";
                        reporter?.Report(progressStatus);

                        progressStatus.Status = "Do CSG";
                        reporter?.Report(progressStatus);
                        var result = BooleanProcessing.Do(keep.obj3D.Mesh, keep.matrix,
                                                          remove.obj3D.Mesh, remove.matrix, 1, reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken);
                        var inverse = keep.matrix.Inverted;
                        result.Transform(inverse);

                        using (keep.obj3D.RebuildLock())
                        {
                            keep.obj3D.Mesh = result;
                        }

                        percentCompleted           += amountPerOperation;
                        progressStatus.Progress0To1 = percentCompleted;
                        reporter?.Report(progressStatus);
                    }

                    remove.obj3D.Visible = false;
                }
            }
        }
예제 #10
0
        private void Subtract(CancellationToken cancellationToken, IProgress <ProgressStatus> reporter)
        {
            SourceContainer.Visible = true;
            RemoveAllButSource();

            var parentOfSubtractTargets = SourceContainer.DescendantsAndSelfMultipleChildrenFirstOrSelf();

            if (parentOfSubtractTargets.Children.Count() < 2)
            {
                if (parentOfSubtractTargets.Children.Count() == 1)
                {
                    this.Children.Add(SourceContainer.Clone());
                    SourceContainer.Visible = false;
                }
                return;
            }

            CleanUpSelectedChildrenNames(this);

            var removeVisibleItems = parentOfSubtractTargets.Children
                                     .Where((i) => SelectedChildren
                                            .Contains(i.Name))
                                     .SelectMany(c => c.VisibleMeshes())
                                     .ToList();

            var keepItems = parentOfSubtractTargets.Children
                            .Where((i) => !SelectedChildren
                                   .Contains(i.Name));

            var keepVisibleItems = keepItems.SelectMany(c => c.VisibleMeshes()).ToList();

            if (removeVisibleItems.Any() &&
                keepVisibleItems.Any())
            {
                var    totalOperations    = removeVisibleItems.Count * keepVisibleItems.Count;
                double amountPerOperation = 1.0 / totalOperations;
                double percentCompleted   = 0;

                ProgressStatus progressStatus = new ProgressStatus();
                progressStatus.Status = "Do CSG";
                foreach (var keep in keepVisibleItems)
                {
                    var resultsMesh     = keep.Mesh;
                    var keepWorldMatrix = keep.WorldMatrix(SourceContainer);

                    foreach (var remove in removeVisibleItems)
                    {
                        resultsMesh = BooleanProcessing.Do(resultsMesh, keepWorldMatrix,
                                                           remove.Mesh, remove.WorldMatrix(SourceContainer),
                                                           1, reporter, amountPerOperation, percentCompleted, 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
                        percentCompleted           += amountPerOperation;
                        progressStatus.Progress0To1 = percentCompleted;
                        reporter?.Report(progressStatus);
                    }

                    // store our results mesh
                    var resultsItem = new Object3D()
                    {
                        Mesh    = resultsMesh,
                        Visible = false
                    };
                    // copy all the properties but the matrix
                    resultsItem.CopyWorldProperties(keep, SourceContainer, Object3DPropertyFlags.All & (~(Object3DPropertyFlags.Matrix | Object3DPropertyFlags.Visible)));
                    // and add it to this
                    this.Children.Add(resultsItem);
                }

                bool first = true;
                foreach (var child in Children)
                {
                    if (first)
                    {
                        // hid the source item
                        child.Visible = false;
                        first         = false;
                    }
                    else
                    {
                        child.Visible = true;
                    }
                }
            }
        }
        public void SubtractAndReplace(CancellationToken cancellationToken, IProgress <ProgressStatus> reporter)
        {
            ResetMeshWrapperMeshes(Object3DPropertyFlags.All, cancellationToken);

            var paintObjects = this.Children
                               .Where((i) => ItemsToSubtract.Contains(i.ID))
                               .SelectMany((h) => h.DescendantsAndSelf())
                               .Where((c) => c.OwnerID == this.ID).ToList();
            var keepObjects = this.Children
                              .Where((i) => !ItemsToSubtract.Contains(i.ID))
                              .SelectMany((h) => h.DescendantsAndSelf())
                              .Where((c) => c.OwnerID == this.ID).ToList();

            if (paintObjects.Any() &&
                keepObjects.Any())
            {
                var    totalOperations    = paintObjects.Count * keepObjects.Count;
                double amountPerOperation = 1.0 / totalOperations;
                double percentCompleted   = 0;

                foreach (var paint in paintObjects.Select((r) => (obj3D: r, matrix: r.WorldMatrix())).ToList())
                {
                    var transformedPaint = paint.obj3D.Mesh.Copy(cancellationToken);
                    transformedPaint.Transform(paint.matrix);
                    var  inverseRemove = paint.matrix.Inverted;
                    Mesh paintMesh     = null;

                    var progressStatus = new ProgressStatus();
                    foreach (var keep in keepObjects.Select((r) => (obj3D: r, matrix: r.WorldMatrix())).ToList())
                    {
                        var transformedKeep = keep.obj3D.Mesh.Copy(cancellationToken);
                        transformedKeep.Transform(keep.matrix);

                        // remove the paint from the original
                        var subtract = BooleanProcessing.Do(keep.obj3D.Mesh, keep.matrix,
                                                            paint.obj3D.Mesh, paint.matrix, 1, reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken);
                        var intersect = BooleanProcessing.Do(keep.obj3D.Mesh, keep.matrix,
                                                             paint.obj3D.Mesh, paint.matrix, 2, reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken);

                        var inverseKeep = keep.matrix.Inverted;
                        subtract.Transform(inverseKeep);
                        using (keep.obj3D.RebuildLock())
                        {
                            keep.obj3D.Mesh = subtract;
                        }

                        // keep all the intersections together
                        if (paintMesh == null)
                        {
                            paintMesh = intersect;
                        }
                        else                         // union into the current paint
                        {
                            paintMesh = BooleanProcessing.Do(paintMesh, Matrix4X4.Identity,
                                                             intersect, Matrix4X4.Identity, 0, reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken);
                        }

                        if (cancellationToken.IsCancellationRequested)
                        {
                            break;
                        }
                    }

                    // move the paint mesh back to its original coordinates
                    paintMesh.Transform(inverseRemove);

                    using (paint.obj3D.RebuildLock())
                    {
                        paint.obj3D.Mesh = paintMesh;
                    }

                    paint.obj3D.Color = paint.obj3D.WorldColor().WithContrast(keepObjects.First().WorldColor(), 2).ToColor();
                }
            }
        }
예제 #12
0
        private void SubtractAndReplace(CancellationToken cancellationToken, IProgress <ProgressStatus> reporter)
        {
            SourceContainer.Visible = true;
            RemoveAllButSource();

            var participants = SourceContainer.VisibleMeshes();

            if (participants.Count() < 2)
            {
                if (participants.Count() == 1)
                {
                    var newMesh = new Object3D();
                    newMesh.CopyProperties(participants.First(), Object3DPropertyFlags.All);
                    newMesh.Mesh = participants.First().Mesh;
                    this.Children.Add(newMesh);
                    SourceContainer.Visible = false;
                }
                return;
            }

            SubtractObject3D_2.CleanUpSelectedChildrenNames(this);

            var paintObjects = this.SourceContainer.VisibleMeshes()
                               .Where((i) => SelectedChildren.Contains(i.Name)).ToList();
            var keepObjects = this.SourceContainer.VisibleMeshes()
                              .Where((i) => !SelectedChildren.Contains(i.Name)).ToList();

            if (paintObjects.Any() &&
                keepObjects.Any())
            {
                var    totalOperations    = paintObjects.Count * keepObjects.Count;
                double amountPerOperation = 1.0 / totalOperations;
                double percentCompleted   = 0;

                ProgressStatus progressStatus = new ProgressStatus();
                progressStatus.Status = "Do CSG";
                foreach (var keep in keepObjects)
                {
                    var keepResultsMesh = keep.Mesh;
                    var keepWorldMatrix = keep.WorldMatrix(SourceContainer);

                    foreach (var paint in paintObjects)
                    {
                        Mesh paintMesh = BooleanProcessing.Do(keepResultsMesh, keepWorldMatrix,
                                                              paint.Mesh, paint.WorldMatrix(SourceContainer),
                                                              2, reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken);

                        keepResultsMesh = BooleanProcessing.Do(keepResultsMesh, keepWorldMatrix,
                                                               paint.Mesh, paint.WorldMatrix(SourceContainer),
                                                               1, reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken);

                        // after the first time we get a result the results mesh is in the right coordinate space
                        keepWorldMatrix = Matrix4X4.Identity;

                        // store our intersection (paint) results mesh
                        var paintResultsItem = new Object3D()
                        {
                            Mesh    = paintMesh,
                            Visible = false
                        };
                        // copy all the properties but the matrix
                        paintResultsItem.CopyProperties(paint, Object3DPropertyFlags.All & (~(Object3DPropertyFlags.Matrix | Object3DPropertyFlags.Visible)));
                        // and add it to this
                        this.Children.Add(paintResultsItem);

                        // report our progress
                        percentCompleted           += amountPerOperation;
                        progressStatus.Progress0To1 = percentCompleted;
                        reporter?.Report(progressStatus);
                    }

                    // store our results mesh
                    var keepResultsItem = new Object3D()
                    {
                        Mesh    = keepResultsMesh,
                        Visible = false
                    };
                    // copy all the properties but the matrix
                    keepResultsItem.CopyProperties(keep, Object3DPropertyFlags.All & (~(Object3DPropertyFlags.Matrix | Object3DPropertyFlags.Visible)));
                    // and add it to this
                    this.Children.Add(keepResultsItem);
                }

                foreach (var child in Children)
                {
                    child.Visible = true;
                }
                SourceContainer.Visible = false;
            }
        }
        private void Intersect(CancellationToken cancellationToken, IProgress <ProgressStatus> reporter)
        {
            SourceContainer.Visible = true;
            RemoveAllButSource();

            var participants = SourceContainer.VisibleMeshes();

            if (participants.Count() < 2)
            {
                if (participants.Count() == 1)
                {
                    var newMesh = new Object3D();
                    newMesh.CopyProperties(participants.First(), Object3DPropertyFlags.All);
                    newMesh.Mesh = participants.First().Mesh;
                    this.Children.Add(newMesh);
                    SourceContainer.Visible = false;
                }
                return;
            }

            var items = participants.Select(i => (i.Mesh, i.WorldMatrix(SourceContainer)));

#if false
            var resultsMesh = BooleanProcessing.DoArray(items,
                                                        CsgModes.Intersect,
                                                        Processing,
                                                        InputResolution,
                                                        OutputResolution,
                                                        reporter,
                                                        cancellationToken);
#else
            var    totalOperations    = items.Count() - 1;
            double amountPerOperation = 1.0 / totalOperations;
            double ratioCompleted     = 0;

            var progressStatus = new ProgressStatus();

            var resultsMesh     = items.First().Item1;
            var keepWorldMatrix = items.First().Item2;

            bool first = true;
            foreach (var next in items)
            {
                if (first)
                {
                    first = false;
                    continue;
                }

                resultsMesh = BooleanProcessing.Do(resultsMesh,
                                                   keepWorldMatrix,
                                                   // other mesh
                                                   next.Item1,
                                                   next.Item2,
                                                   // operation type
                                                   CsgModes.Intersect,
                                                   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

            if (resultsMesh != null)
            {
                var resultsItem = new Object3D()
                {
                    Mesh = resultsMesh
                };
                resultsItem.CopyProperties(participants.First(), Object3DPropertyFlags.All & (~Object3DPropertyFlags.Matrix));
                this.Children.Add(resultsItem);
                SourceContainer.Visible = false;
            }
        }
예제 #14
0
        private void Rebuild(UndoBuffer undoBuffer)
        {
            this.DebugDepth("Rebuild");
            var rebuildLock = RebuildLock();

            ResetMeshWrapperMeshes(Object3DPropertyFlags.All, CancellationToken.None);

            // spin up a task to calculate the paint
            ApplicationController.Instance.Tasks.Execute("Subtract".Localize(), (reporter, cancellationToken) =>
            {
                var progressStatus = new ProgressStatus();

                var paintObjects = this.Children
                                   .Where((i) => ItemsToSubtract.Contains(i.ID))
                                   .SelectMany((h) => h.DescendantsAndSelf())
                                   .Where((c) => c.OwnerID == this.ID).ToList();
                var keepObjects = this.Children
                                  .Where((i) => !ItemsToSubtract.Contains(i.ID))
                                  .SelectMany((h) => h.DescendantsAndSelf())
                                  .Where((c) => c.OwnerID == this.ID).ToList();

                try
                {
                    if (paintObjects.Any() &&
                        keepObjects.Any())
                    {
                        var totalOperations       = paintObjects.Count * keepObjects.Count;
                        double amountPerOperation = 1.0 / totalOperations;
                        double percentCompleted   = 0;

                        foreach (var paint in paintObjects.Select((r) => (obj3D: r, matrix: r.WorldMatrix())).ToList())
                        {
                            var transformedPaint = paint.obj3D.Mesh.Copy(cancellationToken);
                            transformedPaint.Transform(paint.matrix);
                            var inverseRemove = paint.matrix.Inverted;
                            Mesh paintMesh    = null;

                            foreach (var keep in keepObjects.Select((r) => (obj3D: r, matrix: r.WorldMatrix())).ToList())
                            {
                                var transformedKeep = keep.obj3D.Mesh.Copy(cancellationToken);
                                transformedKeep.Transform(keep.matrix);

                                // remove the paint from the original
                                var subtract  = BooleanProcessing.Do(transformedKeep, transformedPaint, 1, reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken);
                                var intersect = BooleanProcessing.Do(transformedKeep, transformedPaint, 2, reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken);

                                var inverseKeep = keep.matrix.Inverted;
                                subtract.Transform(inverseKeep);
                                using (keep.obj3D.RebuildLock())
                                {
                                    keep.obj3D.Mesh = subtract;
                                }

                                // keep all the intersections together
                                if (paintMesh == null)
                                {
                                    paintMesh = intersect;
                                }
                                else                                 // union into the current paint
                                {
                                    paintMesh = BooleanProcessing.Do(transformedKeep, intersect, 0, reporter, amountPerOperation, percentCompleted, progressStatus, cancellationToken);
                                }

                                if (cancellationToken.IsCancellationRequested)
                                {
                                    break;
                                }
                            }

                            // move the paint mesh back to its original coordinates
                            paintMesh.Transform(inverseRemove);

                            using (paint.obj3D.RebuildLock())
                            {
                                paint.obj3D.Mesh = paintMesh;
                            }

                            paint.obj3D.Color = paint.obj3D.WorldColor().WithContrast(keepObjects.First().WorldColor(), 2).ToColor();
                        }
                    }
예제 #15
0
        private void Subtract(CancellationToken cancellationToken, IProgress <ProgressStatus> reporter)
        {
            SourceContainer.Visible = true;
            RemoveAllButSource();

            var parentOfSubtractTargets = SourceContainer.DescendantsAndSelfMultipleChildrenFirstOrSelf();

            if (parentOfSubtractTargets.Children.Count() < 2)
            {
                if (parentOfSubtractTargets.Children.Count() == 1)
                {
                    this.Children.Add(SourceContainer.Clone());
                    SourceContainer.Visible = false;
                }

                return;
            }

            CleanUpSelectedChildrenNames(this);

            var removeVisibleItems = parentOfSubtractTargets.Children
                                     .Where((i) => SelectedChildren
                                            .Contains(i.ID))
                                     .SelectMany(c => c.VisibleMeshes())
                                     .ToList();

            var keepItems = parentOfSubtractTargets.Children
                            .Where((i) => !SelectedChildren
                                   .Contains(i.ID));

            var keepVisibleItems = keepItems.SelectMany(c => c.VisibleMeshes()).ToList();

            if (removeVisibleItems.Any() &&
                keepVisibleItems.Any())
            {
                foreach (var keep in keepVisibleItems)
                {
#if false
                    var items = removeVisibleItems.Select(i => (i.Mesh, i.WorldMatrix(SourceContainer))).ToList();
                    items.Insert(0, (keep.Mesh, keep.Matrix));
                    var resultsMesh = BooleanProcessing.DoArray(items,
                                                                CsgModes.Subtract,
                                                                Processing,
                                                                InputResolution,
                                                                OutputResolution,
                                                                reporter,
                                                                cancellationToken);
#else
                    var    totalOperations    = removeVisibleItems.Count * keepVisibleItems.Count;
                    double amountPerOperation = 1.0 / totalOperations;
                    double ratioCompleted     = 0;

                    var progressStatus = new ProgressStatus
                    {
                        Status = "Do CSG"
                    };

                    var resultsMesh     = keep.Mesh;
                    var keepWorldMatrix = keep.WorldMatrix(SourceContainer);

                    foreach (var remove in removeVisibleItems)
                    {
                        resultsMesh = BooleanProcessing.Do(resultsMesh,
                                                           keepWorldMatrix,
                                                           // other mesh
                                                           remove.Mesh,
                                                           remove.WorldMatrix(SourceContainer),
                                                           // operation type
                                                           CsgModes.Subtract,
                                                           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
                    // store our results mesh
                    var resultsItem = new Object3D()
                    {
                        Mesh    = resultsMesh,
                        Visible = false,
                        OwnerID = keep.ID
                    };

                    // copy all the properties but the matrix
                    resultsItem.CopyWorldProperties(keep, SourceContainer, Object3DPropertyFlags.All & (~(Object3DPropertyFlags.Matrix | Object3DPropertyFlags.Visible)));
                    // and add it to this
                    this.Children.Add(resultsItem);

                    if (!RemoveSubtractObjects)
                    {
                        this.Children.Modify((list) =>
                        {
                            foreach (var item in removeVisibleItems)
                            {
                                var newObject = new Object3D()
                                {
                                    Mesh = item.Mesh
                                };

                                newObject.CopyWorldProperties(item, SourceContainer, Object3DPropertyFlags.All & (~Object3DPropertyFlags.Visible));
                                list.Add(newObject);
                            }
                        });
                    }
                }

                bool first = true;
                foreach (var child in Children)
                {
                    if (first)
                    {
                        // hide the source item
                        child.Visible = false;
                        first         = false;
                    }
                    else
                    {
                        child.Visible = true;
                    }
                }
            }
        }