示例#1
0
        public override Task Rebuild()
        {
            this.DebugDepth("Rebuild");

            var rebuildLock = this.RebuildLock();

            return(ApplicationController.Instance.Tasks.Execute(
                       "Mirror".Localize(),
                       null,
                       (reporter, cancellationToken) =>
            {
                SourceContainer.Visible = true;
                RemoveAllButSource();

                var oldMatrix = this.Matrix;
                this.Matrix = Matrix4X4.Identity;

                var mirrorMatrix = Matrix4X4.Identity;
                switch (MirrorOn)
                {
                case MirrorAxis.X_Axis:
                    mirrorMatrix = this.ApplyAtBoundsCenter(Matrix4X4.CreateScale(-1, 1, 1));
                    break;

                case MirrorAxis.Y_Axis:
                    mirrorMatrix = this.ApplyAtBoundsCenter(Matrix4X4.CreateScale(1, -1, 1));
                    break;

                case MirrorAxis.Z_Axis:
                    mirrorMatrix = this.ApplyAtBoundsCenter(Matrix4X4.CreateScale(1, 1, -1));
                    break;
                }

                foreach (var sourceItem in SourceContainer.VisibleMeshes())
                {
                    var originalMesh = sourceItem.Mesh;
                    var transformedMesh = originalMesh.Copy(CancellationToken.None);

                    var sourceToThisMatrix = sourceItem.WorldMatrix(this);

                    // move it to us then mirror then move it back
                    transformedMesh.Transform(sourceToThisMatrix * mirrorMatrix * sourceToThisMatrix.Inverted);

                    transformedMesh.ReverseFaces();

                    var newMesh = new Object3D()
                    {
                        Mesh = transformedMesh
                    };
                    newMesh.CopyWorldProperties(sourceItem, this, Object3DPropertyFlags.All, false);
                    this.Children.Add(newMesh);
                }

                this.Matrix = oldMatrix;
                SourceContainer.Visible = false;
                rebuildLock.Dispose();
                Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Children));
                return Task.CompletedTask;
            }));
        }
示例#2
0
        public override Task Rebuild()
        {
            this.DebugDepth("Rebuild");

            var rebuildLocks = this.RebuilLockAll();

            var valuesChanged = false;

            // check if we have be initialized

            return(TaskBuilder(
                       "Repair".Localize(),
                       (reporter, cancellationToken) =>
            {
                SourceContainer.Visible = true;
                RemoveAllButSource();

                var inititialVertices = 0;
                var inititialFaces = 0;
                var finalVertices = 0;
                var finalFaces = 0;
                foreach (var sourceItem in SourceContainer.VisibleMeshes())
                {
                    var originalMesh = sourceItem.Mesh;
                    inititialFaces += originalMesh.Faces.Count;
                    inititialVertices += originalMesh.Vertices.Count;
                    var repairedMesh = Repair(originalMesh, cancellationToken);
                    finalFaces += repairedMesh.Faces.Count;
                    finalVertices += repairedMesh.Vertices.Count;

                    var repairedChild = new Object3D()
                    {
                        Mesh = repairedMesh
                    };
                    repairedChild.CopyWorldProperties(sourceItem, this, Object3DPropertyFlags.All, false);
                    this.Children.Add(repairedChild);
                }

                this.InitialFaces = inititialFaces;
                this.InitialVertices = inititialVertices;
                this.FinalFaces = finalFaces;
                this.FinalVertices = finalVertices;

                SourceContainer.Visible = false;

                UiThread.RunOnIdle(() =>
                {
                    rebuildLocks.Dispose();
                    if (valuesChanged)
                    {
                        Invalidate(InvalidateType.DisplayValues);
                    }
                    Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Children));
                });

                return Task.CompletedTask;
            }));
        }
        public override Task Rebuild()
        {
            this.DebugDepth("Rebuild");

            var rebuildLocks = this.RebuilLockAll();

            var valuesChanged = false;

            return(TaskBuilder(
                       "Plane Cut".Localize(),
                       (reporter, cancellationToken) =>
            {
                var newChildren = new List <Object3D>();
                var root = SourceContainer.Children.First();
                root = root == null ? SourceContainer : root;
                foreach (var sourceItem in SourceContainer.VisibleMeshes())
                {
                    var reducedMesh = Cut(sourceItem);

                    var newMesh = new Object3D()
                    {
                        Mesh = reducedMesh,
                        OwnerID = sourceItem.ID
                    };
                    newMesh.CopyWorldProperties(sourceItem, root, Object3DPropertyFlags.All);
                    newChildren.Add(newMesh);
                }

                var sourceContainer = SourceContainer;
                this.Children.Modify(list =>
                {
                    list.Clear();
                    list.Add(sourceContainer);
                    foreach (var child in newChildren)
                    {
                        list.Add(child);
                    }
                    sourceContainer.Visible = false;
                });

                UiThread.RunOnIdle(() =>
                {
                    rebuildLocks.Dispose();
                    Invalidate(InvalidateType.DisplayValues);
                    Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Children));
                });

                return Task.CompletedTask;
            }));
        }
示例#4
0
        public override Task Rebuild()
        {
            this.DebugDepth("Rebuild");

            bool valuesChanged = false;

            // ensure we have good values
            StartPercent = agg_basics.Clamp(StartPercent, 0, 100, ref valuesChanged);

            if (Diameter < 1 || Diameter > 100000)
            {
                if (Diameter == double.MaxValue)
                {
                    var aabb = this.GetAxisAlignedBoundingBox();
                    // uninitialized set to a reasonable value
                    Diameter = (int)aabb.XSize;
                }

                Diameter      = Math.Min(100000, Math.Max(1, Diameter));
                valuesChanged = true;
            }

            MinSidesPerRotation = agg_basics.Clamp(MinSidesPerRotation, 3, 360, ref valuesChanged);

            var rebuildLocks = this.RebuilLockAll();

            return(ApplicationController.Instance.Tasks.Execute(
                       "Curve".Localize(),
                       null,
                       (reporter, cancellationToken) =>
            {
                var sourceAabb = this.SourceContainer.GetAxisAlignedBoundingBox();

                var radius = Diameter / 2;
                var circumference = MathHelper.Tau * radius;
                double numRotations = sourceAabb.XSize / circumference;
                double numberOfCuts = numRotations * MinSidesPerRotation;
                double cutSize = sourceAabb.XSize / numberOfCuts;
                double cutPosition = sourceAabb.MinXYZ.X + cutSize;
                var cuts = new List <double>();
                for (int i = 0; i < numberOfCuts; i++)
                {
                    cuts.Add(cutPosition);
                    cutPosition += cutSize;
                }

                var rotationCenter = new Vector3(sourceAabb.MinXYZ.X + (sourceAabb.MaxXYZ.X - sourceAabb.MinXYZ.X) * (StartPercent / 100),
                                                 BendCcw ? sourceAabb.MaxXYZ.Y + radius : sourceAabb.MinXYZ.Y - radius,
                                                 sourceAabb.Center.Z);

                var curvedChildren = new List <IObject3D>();

                var status = new ProgressStatus();

                foreach (var sourceItem in SourceContainer.VisibleMeshes())
                {
                    var originalMesh = sourceItem.Mesh;
                    status.Status = "Copy Mesh".Localize();
                    reporter.Report(status);
                    var transformedMesh = originalMesh.Copy(CancellationToken.None);
                    var itemMatrix = sourceItem.WorldMatrix(SourceContainer);

                    // transform into this space
                    transformedMesh.Transform(itemMatrix);

                    if (SplitMesh)
                    {
                        status.Status = "Split Mesh".Localize();
                        reporter.Report(status);

                        // split the mesh along the x axis
                        transformedMesh.SplitOnPlanes(Vector3.UnitX, cuts, cutSize / 8);
                    }

                    for (int i = 0; i < transformedMesh.Vertices.Count; i++)
                    {
                        var position = transformedMesh.Vertices[i];

                        var angleToRotate = ((position.X - rotationCenter.X) / circumference) * MathHelper.Tau - MathHelper.Tau / 4;
                        var distanceFromCenter = rotationCenter.Y - position.Y;
                        if (!BendCcw)
                        {
                            angleToRotate = -angleToRotate;
                            distanceFromCenter = -distanceFromCenter;
                        }

                        var rotatePosition = new Vector3Float(Math.Cos(angleToRotate), Math.Sin(angleToRotate), 0) * distanceFromCenter;
                        rotatePosition.Z = position.Z;
                        transformedMesh.Vertices[i] = rotatePosition + new Vector3Float(rotationCenter.X, radius + sourceAabb.MaxXYZ.Y, 0);
                    }

                    // transform back into item local space
                    transformedMesh.Transform(Matrix4X4.CreateTranslation(-rotationCenter) * itemMatrix.Inverted);

                    if (SplitMesh)
                    {
                        status.Status = "Merge Vertices".Localize();
                        reporter.Report(status);

                        transformedMesh.MergeVertices(.1);
                    }

                    transformedMesh.CalculateNormals();

                    var curvedChild = new Object3D()
                    {
                        Mesh = transformedMesh
                    };
                    curvedChild.CopyWorldProperties(sourceItem, SourceContainer, Object3DPropertyFlags.All, false);
                    curvedChild.Visible = true;
                    curvedChild.Translate(new Vector3(rotationCenter));
                    if (!BendCcw)
                    {
                        curvedChild.Translate(0, -sourceAabb.YSize - Diameter, 0);
                    }

                    curvedChildren.Add(curvedChild);
                }

                RemoveAllButSource();
                this.SourceContainer.Visible = false;

                this.Children.Modify((list) =>
                {
                    list.AddRange(curvedChildren);
                });

                UiThread.RunOnIdle(() =>
                {
                    rebuildLocks.Dispose();
                    if (valuesChanged)
                    {
                        Invalidate(InvalidateType.DisplayValues);
                    }
                    Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Children));
                });

                return Task.CompletedTask;
            }));
        }
示例#5
0
        public override Task Rebuild()
        {
            this.DebugDepth("Rebuild");

            bool valuesChanged = false;

            if (Angle < 1 || Angle > 100000)
            {
                Angle         = Math.Min(100000, Math.Max(1, Angle));
                valuesChanged = true;
            }

            if (RotationDistance < 0 || RotationDistance > 100000)
            {
                RotationDistance = Math.Min(100000, Math.Max(0, RotationDistance));
                valuesChanged    = true;
            }

            if (RotationSlices < 3 || RotationSlices > 300)
            {
                RotationSlices = Math.Min(300, Math.Max(3, RotationSlices));
                valuesChanged  = true;
            }

            if (EndHeightPercent < 1 || EndHeightPercent > 100)
            {
                EndHeightPercent = Math.Min(100, Math.Max(1, EndHeightPercent));
                valuesChanged    = true;
            }

            if (StartHeightPercent < 0 || StartHeightPercent > EndHeightPercent - 1)
            {
                StartHeightPercent = Math.Min(EndHeightPercent - 1, Math.Max(0, StartHeightPercent));
                valuesChanged      = true;
            }

            if (OverrideRadius < .01)
            {
                OverrideRadius = Math.Max(this.GetAxisAlignedBoundingBox().XSize, this.GetAxisAlignedBoundingBox().YSize);
                valuesChanged  = true;
            }

            var rebuildLocks = this.RebuilLockAll();

            return(ApplicationController.Instance.Tasks.Execute(
                       "Twist".Localize(),
                       null,
                       (reporter, cancellationToken) =>
            {
                var sourceAabb = this.SourceContainer.GetAxisAlignedBoundingBox();

                var bottom = sourceAabb.MinXYZ.Z;
                var top = sourceAabb.ZSize * EndHeightPercent / 100.0;
                var size = sourceAabb.ZSize;
                if (Advanced)
                {
                    bottom += sourceAabb.ZSize * StartHeightPercent / 100.0;
                    size = top - bottom;
                }

                double numberOfCuts = RotationSlices;

                double cutSize = size / numberOfCuts;
                var cuts = new List <double>();
                for (int i = 0; i < numberOfCuts + 1; i++)
                {
                    var ratio = i / numberOfCuts;
                    if (Advanced)
                    {
                        var goal = ratio;
                        var current = .5;
                        var next = .25;
                        // look for an x value that equals the goal
                        for (int j = 0; j < 64; j++)
                        {
                            var xAtY = Easing.Specify(EasingType, EasingOption, current);
                            if (xAtY < goal)
                            {
                                current += next;
                            }
                            else if (xAtY > goal)
                            {
                                current -= next;
                            }

                            next *= .5;
                        }

                        ratio = current;
                    }

                    cuts.Add(bottom - cutSize + (size * ratio));
                }

                // get the rotation from the center of the circumscribed circle of the convex hull
                var enclosingCircle = SourceContainer.GetSmallestEnclosingCircleAlongZ();
                var rotationCenter = enclosingCircle.Center + RotationOffset;

                var twistedChildren = new List <IObject3D>();

                var status = new ProgressStatus();

                foreach (var sourceItem in SourceContainer.VisibleMeshes())
                {
                    var originalMesh = sourceItem.Mesh;
                    status.Status = "Copy Mesh".Localize();
                    reporter.Report(status);
                    var transformedMesh = originalMesh.Copy(CancellationToken.None);
                    var itemMatrix = sourceItem.WorldMatrix(SourceContainer);

                    // transform into this space
                    transformedMesh.Transform(itemMatrix);

                    status.Status = "Split Mesh".Localize();
                    reporter.Report(status);

                    // split the mesh along the z axis
                    transformedMesh.SplitOnPlanes(Vector3.UnitZ, cuts, cutSize / 8);

                    for (int i = 0; i < transformedMesh.Vertices.Count; i++)
                    {
                        var position = transformedMesh.Vertices[i];

                        var ratio = (position.Z - bottom) / size;

                        if (Advanced)
                        {
                            if (position.Z < bottom)
                            {
                                ratio = 0;
                            }
                            else if (position.Z > top)
                            {
                                ratio = 1;
                            }
                            else
                            {
                                ratio = (position.Z - bottom) / size;
                                ratio = Easing.Specify(EasingType, EasingOption, ratio);
                            }
                        }

                        var angleToRotate = ratio * Angle / 360.0 * MathHelper.Tau;
                        if (RotationType == RotationTypes.Distance)
                        {
                            IRadiusProvider radiusProvider = RadiusProvider;

                            // start off with assuming we want to set the radius
                            var radius = this.OverrideRadius;
                            if (radiusProvider != null && !this.EditRadius)
                            {
                                // have a radius provider and not wanting to edit
                                radius = radiusProvider.Radius;
                            }
                            else if (!this.EditRadius)
                            {
                                // not wanting to edit
                                radius = enclosingCircle.Radius;
                            }

                            if (this.PreferedRadius != radius)
                            {
                                this.PreferedRadius = radius;
                                this.OverrideRadius = radius;
                                UiThread.RunOnIdle(() => Invalidate(InvalidateType.DisplayValues));
                            }

                            angleToRotate = ratio * (RotationDistance / radius);
                        }

                        if (!TwistCw)
                        {
                            angleToRotate = -angleToRotate;
                        }

                        var positionXy = new Vector2(position) - rotationCenter;
                        positionXy.Rotate(angleToRotate);
                        positionXy += rotationCenter;
                        transformedMesh.Vertices[i] = new Vector3Float(positionXy.X, positionXy.Y, position.Z);
                    }

                    // transform back into item local space
                    transformedMesh.Transform(itemMatrix.Inverted);

                    //transformedMesh.MergeVertices(.1);
                    transformedMesh.CalculateNormals();

                    var twistedChild = new Object3D()
                    {
                        Mesh = transformedMesh
                    };
                    twistedChild.CopyWorldProperties(sourceItem, SourceContainer, Object3DPropertyFlags.All, false);
                    twistedChild.Visible = true;

                    twistedChildren.Add(twistedChild);
                }

                RemoveAllButSource();
                this.SourceContainer.Visible = false;

                this.Children.Modify((list) =>
                {
                    list.AddRange(twistedChildren);
                });

                rebuildLocks.Dispose();

                if (valuesChanged)
                {
                    Invalidate(InvalidateType.DisplayValues);
                }

                Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Children));

                return Task.CompletedTask;
            }));
        }
示例#6
0
        public override Task Rebuild()
        {
            this.DebugDepth("Rebuild");

            var rebuildLocks = this.RebuilLockAll();

            return(ApplicationController.Instance.Tasks.Execute(
                       "Pinch".Localize(),
                       null,
                       (reporter, cancellationToken) =>
            {
                SourceContainer.Visible = true;
                RemoveAllButSource();

                // remember the current matrix then clear it so the parts will rotate at the original wrapped position
                var currentMatrix = Matrix;
                Matrix = Matrix4X4.Identity;

                var aabb = SourceContainer.GetAxisAlignedBoundingBox();

                bool valuesChanged = false;

                PinchPercent = agg_basics.Clamp(PinchPercent, 0, 3, ref valuesChanged);

                foreach (var sourceItem in SourceContainer.VisibleMeshes())
                {
                    var originalMesh = sourceItem.Mesh;
                    var transformedMesh = originalMesh.Copy(CancellationToken.None);
                    var itemMatrix = sourceItem.WorldMatrix(SourceContainer);
                    var invItemMatrix = itemMatrix.Inverted;

                    for (int i = 0; i < originalMesh.Vertices.Count; i++)
                    {
                        var pos = originalMesh.Vertices[i];
                        pos = pos.Transform(itemMatrix);

                        var ratioToApply = PinchPercent / 100.0;

                        var distFromCenter = pos.X - aabb.Center.X;
                        var distanceToPinch = distFromCenter * (1 - ratioToApply);
                        var delta = (aabb.Center.X + distFromCenter * ratioToApply) - pos.X;

                        // find out how much to pinch based on y position
                        var amountOfRatio = (pos.Y - aabb.MinXYZ.Y) / aabb.YSize;

                        var newPos = new Vector3Float(pos.X + delta * amountOfRatio, pos.Y, pos.Z);

                        transformedMesh.Vertices[i] = newPos.Transform(invItemMatrix);
                    }

                    transformedMesh.CalculateNormals();

                    var newMesh = new Object3D()
                    {
                        Mesh = transformedMesh
                    };
                    newMesh.CopyWorldProperties(sourceItem, this, Object3DPropertyFlags.All, false);
                    this.Children.Add(newMesh);
                }

                // set the matrix back
                Matrix = currentMatrix;
                SourceContainer.Visible = false;
                rebuildLocks.Dispose();

                if (valuesChanged)
                {
                    Invalidate(InvalidateType.DisplayValues);
                }

                Invalidate(InvalidateType.Children);
                return Task.CompletedTask;
            }));
        }
示例#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 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;
                    }
                }
            }
        }
示例#9
0
        public override Task Rebuild()
        {
            this.DebugDepth("Rebuild");

            bool valuesChanged = false;

            // check if we have initialized the Axis
            if (Axis.Origin.X == double.NegativeInfinity)
            {
                // make it something reasonable (just to the left of the aabb of the object)
                Axis.Origin   = this.GetAxisAlignedBoundingBox().Center;
                valuesChanged = true;
            }

            var rebuildLocks = this.RebuilLockAll();

            return(ApplicationController.Instance.Tasks.Execute(
                       "Split".Localize(),
                       null,
                       (reporter, cancellationToken) =>
            {
                var splitChildren = new List <IObject3D>();

                var status = new ProgressStatus();

                foreach (var sourceItem in SourceContainer.VisibleMeshes())
                {
                    var originalMesh = sourceItem.Mesh;
                    status.Status = "Copy Mesh".Localize();
                    reporter.Report(status);
                    var transformedMesh = originalMesh.Copy(CancellationToken.None);
                    var itemMatrix = sourceItem.WorldMatrix(SourceContainer);

                    // transform into this space
                    transformedMesh.Transform(itemMatrix);

                    status.Status = "Split Mesh".Localize();
                    reporter.Report(status);

                    // split faces until they are small enough
                    transformedMesh.Split(Axis.GetPlane());

                    // transform back into item local space
                    transformedMesh.Transform(itemMatrix.Inverted);

                    var splitChild = new Object3D()
                    {
                        Mesh = transformedMesh
                    };

                    splitChild.CopyWorldProperties(sourceItem, SourceContainer, Object3DPropertyFlags.All);
                    splitChild.Visible = true;

                    splitChildren.Add(splitChild);
                }

                RemoveAllButSource();
                this.SourceContainer.Visible = false;

                this.Children.Modify((list) =>
                {
                    list.AddRange(splitChildren);
                });

                rebuildLocks.Dispose();

                if (valuesChanged)
                {
                    Invalidate(InvalidateType.DisplayValues);
                }

                Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Children));

                return Task.CompletedTask;
            }));
        }
        public override Task Rebuild()
        {
            this.DebugDepth("Rebuild");

            bool valuesChanged = false;

            if (MaxEdgeLength < .01)
            {
                MaxEdgeLength = Math.Max(.01, MaxEdgeLength);
                valuesChanged = true;
            }

            if (MaxAllowedFaces < 100)
            {
                MaxAllowedFaces = Math.Max(100, MaxAllowedFaces);
                valuesChanged   = true;
            }

            var rebuildLocks = this.RebuilLockAll();

            return(ApplicationController.Instance.Tasks.Execute(
                       "Subdivide".Localize(),
                       null,
                       (reporter, cancellationToken) =>
            {
                var subdividedChildren = new List <IObject3D>();

                var status = new ProgressStatus();

                foreach (var sourceItem in SourceContainer.VisibleMeshes())
                {
                    var originalMesh = sourceItem.Mesh;
                    status.Status = "Copy Mesh".Localize();
                    reporter.Report(status);
                    var transformedMesh = originalMesh.Copy(CancellationToken.None);
                    var itemMatrix = sourceItem.WorldMatrix(SourceContainer);

                    // transform into this space
                    transformedMesh.Transform(itemMatrix);

                    status.Status = "Split Mesh".Localize();
                    reporter.Report(status);

                    // split faces until they are small enough
                    var newVertices = new List <Vector3Float>();
                    var newFaces = new List <Face>();

                    for (int i = 0; i < transformedMesh.Faces.Count; i++)
                    {
                        var face = transformedMesh.Faces[i];

                        SplitRecursive(new Vector3Float[]
                        {
                            transformedMesh.Vertices[face.v0],
                            transformedMesh.Vertices[face.v1],
                            transformedMesh.Vertices[face.v2]
                        },
                                       face.normal,
                                       newVertices,
                                       newFaces);
                    }

                    transformedMesh.Vertices = newVertices;
                    transformedMesh.Faces = new FaceList(newFaces);

                    // transform back into item local space
                    transformedMesh.Transform(itemMatrix.Inverted);

                    var subdividedChild = new Object3D()
                    {
                        Mesh = transformedMesh
                    };
                    subdividedChild.CopyWorldProperties(sourceItem, SourceContainer, Object3DPropertyFlags.All);
                    subdividedChild.Visible = true;

                    subdividedChildren.Add(subdividedChild);
                }

                RemoveAllButSource();
                this.SourceContainer.Visible = false;

                this.Children.Modify((list) =>
                {
                    list.AddRange(subdividedChildren);
                });

                rebuildLocks.Dispose();

                if (valuesChanged)
                {
                    Invalidate(InvalidateType.DisplayValues);
                }

                Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Children));

                return Task.CompletedTask;
            }));
        }
示例#11
0
        public override Task Rebuild()
        {
            this.DebugDepth("Rebuild");

            bool propertyUpdated = Diameter == double.MinValue;

            if (StartPercent < 0 ||
                StartPercent > 100)
            {
                StartPercent    = Math.Min(100, Math.Max(0, StartPercent));
                propertyUpdated = true;
            }

            var originalAabb = this.GetAxisAlignedBoundingBox();

            var rebuildLocks = this.RebuilLockAll();

            return(ApplicationController.Instance.Tasks.Execute(
                       "Curve".Localize(),
                       null,
                       (reporter, cancellationToken) =>
            {
                using (new CenterAndHeightMantainer(this))
                {
                    this.Translate(-rotationOffset);
                    SourceContainer.Visible = true;
                    RemoveAllButSource();

                    // remember the current matrix then clear it so the parts will rotate at the original wrapped position
                    var currentMatrix = Matrix;
                    Matrix = Matrix4X4.Identity;

                    var aabb = this.GetAxisAlignedBoundingBox();
                    if (Diameter == double.MinValue)
                    {
                        // uninitialized set to a reasonable value
                        Diameter = (int)aabb.XSize;
                        // TODO: ensure that the editor display value is updated
                    }

                    if (Diameter > 0)
                    {
                        var radius = Diameter / 2;
                        var circumference = MathHelper.Tau * radius;
                        var rotationCenter = new Vector3(aabb.MinXYZ.X + (aabb.MaxXYZ.X - aabb.MinXYZ.X) * (StartPercent / 100), aabb.MaxXYZ.Y + radius, aabb.Center.Z);

                        rotationOffset = rotationCenter;
                        if (!BendCcw)
                        {
                            // fix the stored center so we draw correctly
                            rotationOffset.Y = aabb.MinXYZ.Y - radius;
                        }

                        foreach (var sourceItem in SourceContainer.VisibleMeshes())
                        {
                            var originalMesh = sourceItem.Mesh;
                            var transformedMesh = originalMesh.Copy(CancellationToken.None);
                            var itemMatrix = sourceItem.WorldMatrix(SourceContainer);

                            // split the mesh along the x axis
                            double numRotations = aabb.XSize / circumference;
                            double numberOfCuts = numRotations * MinSidesPerRotation;
                            //SplitMeshAlongX(transformedMesh, numberOfCuts);

                            if (!BendCcw)
                            {
                                // rotate around so it will bend correctly
                                itemMatrix *= Matrix4X4.CreateTranslation(0, -aabb.MaxXYZ.Y, 0);
                                itemMatrix *= Matrix4X4.CreateRotationX(MathHelper.Tau / 2);
                                itemMatrix *= Matrix4X4.CreateTranslation(0, aabb.MaxXYZ.Y - aabb.YSize, 0);
                            }

                            var invItemMatrix = itemMatrix.Inverted;

                            for (int i = 0; i < transformedMesh.Vertices.Count; i++)
                            {
                                var worldPosition = transformedMesh.Vertices[i].Transform((Matrix4X4)itemMatrix);

                                var angleToRotate = ((worldPosition.X - rotationCenter.X) / circumference) * MathHelper.Tau - MathHelper.Tau / 4;
                                var distanceFromCenter = rotationCenter.Y - worldPosition.Y;

                                var rotatePosition = new Vector3Float(Math.Cos(angleToRotate), Math.Sin(angleToRotate), 0) * distanceFromCenter;
                                rotatePosition.Z = worldPosition.Z;
                                var worldWithBend = rotatePosition + new Vector3Float(rotationCenter.X, radius + aabb.MaxXYZ.Y, 0);

                                transformedMesh.Vertices[i] = worldWithBend.Transform(invItemMatrix) - new Vector3Float(rotationOffset);
                            }

                            transformedMesh.MarkAsChanged();
                            transformedMesh.CalculateNormals();

                            var newMesh = new Object3D()
                            {
                                Mesh = transformedMesh
                            };
                            newMesh.CopyWorldProperties(sourceItem, this, Object3DPropertyFlags.All);
                            this.Children.Add(newMesh);
                        }

                        // set the matrix back
                        Matrix = currentMatrix;
                        this.Translate(new Vector3(rotationOffset));
                        SourceContainer.Visible = false;
                        rebuildLocks.Dispose();
                    }
                    Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Children));
                }

                return Task.CompletedTask;
            }));
        }
        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;
                    }
                }
            }
        }