Example #1
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;
        }
        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;
            }
        }
        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;
                    }
                }
            }
        }