Example #1
0
        // Transform by quaternion
        public void PlaneTransformTest2()
        {
            Plane <float> target = new Plane <float>(1, 2, 3, 4);

            target = Plane.Normalize(target);

            Matrix4X4 <float> m =
                Matrix4X4.CreateRotationX(MathHelper.ToRadians(30.0f)) *
                Matrix4X4.CreateRotationY(MathHelper.ToRadians(30.0f)) *
                Matrix4X4.CreateRotationZ(MathHelper.ToRadians(30.0f));
            Quaternion <float> q = Quaternion <float> .CreateFromRotationMatrix(m);

            Plane <float> expected = new Plane <float>();
            float         x = target.Normal.X, y = target.Normal.Y, z = target.Normal.Z, w = target.Distance;

            expected.Normal = new Vector3D <float>(
                x * m.M11 + y * m.M21 + z * m.M31 + w * m.M41,
                x * m.M12 + y * m.M22 + z * m.M32 + w * m.M42,
                x * m.M13 + y * m.M23 + z * m.M33 + w * m.M43);
            expected.Distance = x * m.M14 + y * m.M24 + z * m.M34 + w * m.M44;

            Plane <float> actual;

            actual = Plane.Transform(target, q);
            Assert.True(MathHelper.Equal(expected, actual), "Plane<float>.Transform did not return the expected value.");
        }
Example #2
0
        public override Task Rebuild()
        {
            this.DebugDepth("Rebuild");
            bool valuesChanged = false;

            using (RebuildLock())
            {
                var sides = Sides.ClampIfNotCalculated(this, 3, 180, ref valuesChanged);
                using (new CenterAndHeightMaintainer(this))
                {
                    var path = new VertexStorage();
                    path.MoveTo(Width.Value(this) / 2, 0);

                    for (int i = 1; i < sides; i++)
                    {
                        var angle = MathHelper.Tau * i / 2 / (sides - 1);
                        path.LineTo(Math.Cos(angle) * Width.Value(this) / 2, Math.Sin(angle) * Width.Value(this) / 2);
                    }

                    var mesh = VertexSourceToMesh.Extrude(path, Depth.Value(this));
                    mesh.Transform(Matrix4X4.CreateRotationX(MathHelper.Tau / 4));
                    Mesh = mesh;
                }
            }

            Invalidate(InvalidateType.DisplayValues);

            Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Mesh));
            return(Task.CompletedTask);
        }
 public void TestGetHashCode()
 {
     {
         Vector2 a = new Vector2(10, 11);
         Vector2 b = new Vector2(10, 11);
         Assert.IsTrue(a.GetHashCode() == b.GetHashCode());
     }
     {
         Vector3 a = new Vector3(10, 11, 12);
         Vector3 b = new Vector3(10, 11, 12);
         Assert.IsTrue(a.GetHashCode() == b.GetHashCode());
     }
     {
         Vector4 a = new Vector4(10, 11, 12, 13);
         Vector4 b = new Vector4(10, 11, 12, 13);
         Assert.IsTrue(a.GetHashCode() == b.GetHashCode());
     }
     {
         Quaternion a = new Quaternion(10, 11, 12, 13);
         Quaternion b = new Quaternion(10, 11, 12, 13);
         Assert.IsTrue(a.GetHashCode() == b.GetHashCode());
     }
     {
         Matrix4X4 a = Matrix4X4.CreateRotationX(3);
         Matrix4X4 b = Matrix4X4.CreateRotationX(3);
         Assert.IsTrue(a.GetHashCode() == b.GetHashCode());
     }
 }
Example #4
0
        private void Rebuild(UndoBuffer undoBuffer)
        {
            this.DebugDepth("Rebuild");

            using (RebuildLock())
            {
                var startingAabb = this.GetAxisAlignedBoundingBox();

                // remove whatever rotation has been applied (they go in reverse order)
                Matrix = Matrix4X4.Identity;

                // add the current rotation
                Matrix = this.ApplyAtPosition(startingAabb.Center, Matrix4X4.CreateRotationX(MathHelper.DegreesToRadians(RotationXDegrees)));
                Matrix = this.ApplyAtPosition(startingAabb.Center, Matrix4X4.CreateRotationY(MathHelper.DegreesToRadians(RotationYDegrees)));
                Matrix = this.ApplyAtPosition(startingAabb.Center, Matrix4X4.CreateRotationZ(MathHelper.DegreesToRadians(RotationZDegrees)));

                if (startingAabb.ZSize > 0)
                {
                    // If the part was already created and at a height, maintain the height.
                    PlatingHelper.PlaceMeshAtHeight(this, startingAabb.minXYZ.Z);
                }
            }

            Invalidate(new InvalidateArgs(this, InvalidateType.Matrix, null));
        }
Example #5
0
        private void Rebuild(UndoBuffer undoBuffer)
        {
            this.DebugDepth("Rebuild");
            using (RebuildLock())
            {
                var aabb = this.GetAxisAlignedBoundingBox();

                var path = new VertexStorage();
                path.MoveTo(Width / 2, 0);

                for (int i = 1; i < Sides; i++)
                {
                    var angle = MathHelper.Tau * i / 2 / (Sides - 1);
                    path.LineTo(Math.Cos(angle) * Width / 2, Math.Sin(angle) * Width / 2);
                }

                var mesh = VertexSourceToMesh.Extrude(path, Depth);
                mesh.Transform(Matrix4X4.CreateRotationX(MathHelper.Tau / 4));
                Mesh = mesh;

                if (aabb.ZSize > 0)
                {
                    // If the part was already created and at a height, maintain the height.
                    PlatingHelper.PlaceMeshAtHeight(this, aabb.minXYZ.Z);
                }
            }

            Invalidate(new InvalidateArgs(this, InvalidateType.Mesh));
        }
Example #6
0
        // Transform by matrix
        public void PlaneTransformTest1()
        {
            Plane <float> target = new Plane <float>(1, 2, 3, 4);

            target = Plane.Normalize(target);

            Matrix4X4 <float> m =
                Matrix4X4.CreateRotationX(MathHelper.ToRadians(30.0f)) *
                Matrix4X4.CreateRotationY(MathHelper.ToRadians(30.0f)) *
                Matrix4X4.CreateRotationZ(MathHelper.ToRadians(30.0f));

            m.M41 = 10.0f;
            m.M42 = 20.0f;
            m.M43 = 30.0f;

            Plane <float>     expected = new Plane <float>();
            Matrix4X4 <float> inv;

            Matrix4X4.Invert(m, out inv);
            Matrix4X4 <float> itm = Matrix4X4.Transpose(inv);
            float             x = target.Normal.X, y = target.Normal.Y, z = target.Normal.Z, w = target.Distance;

            expected.Normal = new Vector3D <float>(
                x * itm.M11 + y * itm.M21 + z * itm.M31 + w * itm.M41,
                x * itm.M12 + y * itm.M22 + z * itm.M32 + w * itm.M42,
                x * itm.M13 + y * itm.M23 + z * itm.M33 + w * itm.M43);
            expected.Distance = x * itm.M14 + y * itm.M24 + z * itm.M34 + w * itm.M44;

            Plane <float> actual;

            actual = Plane.Transform(target, m);
            Assert.True(MathHelper.Equal(expected, actual), "Plane<float>.Transform did not return the expected value.");
        }
Example #7
0
        public void RotateAbsolute(double x, double y, double z)
        {
            Matrix4X4 M1 = Matrix4X4.Identity;
            Matrix4X4 M2 = Matrix4X4.Identity;
            Matrix4X4 M3 = Matrix4X4.Identity;
            Matrix4X4 M4 = Matrix4X4.Identity;
            Vector3   save1;

            // save the old position
            save1.x = AxisToWorld[3, 0];
            save1.y = AxisToWorld[3, 1];
            save1.z = AxisToWorld[3, 2];

            M1 = Matrix4X4.CreateRotationX(x);
            M2 = Matrix4X4.CreateRotationY(y);
            M3 = Matrix4X4.CreateRotationZ(z);
            // 1 * 2 * 3
            M4          = M2 * M1;
            AxisToWorld = M3 * M4;

            // stuff the old position back in
            AxisToWorld[3, 0] = save1.x;
            AxisToWorld[3, 1] = save1.y;
            AxisToWorld[3, 2] = save1.z;

            AxisToWorld = Matrix4X4.Invert(WorldToAxis);
        }
Example #8
0
        public void Can_Rotate_Point_Around_X()
        {
            var point       = new Point(0, 1, 0);
            var halfQuarter = Matrix4X4.CreateRotationX(Math.PI / 4);
            var fullQuarter = Matrix4X4.CreateRotationX(Math.PI / 2);

            (halfQuarter * point).ShouldBe(new Point(0, Math.Sqrt(2) / 2, Math.Sqrt(2) / 2));
            (fullQuarter * point).ShouldBe(new Point(0, 0, 1));
            (halfQuarter.Invert().inverse *point).ShouldBe(new Point(0, Math.Sqrt(2) / 2, -Math.Sqrt(2) / 2));
        }
        public override Task Rebuild()
        {
            this.DebugDepth("Rebuild");
            bool valuesChanged = false;

            var roundSegments = RoundSegments.ClampIfNotCalculated(this, 2, 90, ref valuesChanged);

            Invalidate(InvalidateType.DisplayValues);

            using (RebuildLock())
            {
                var height = Height.Value(this);
                var width  = Width.Value(this);
                using (new CenterAndHeightMaintainer(this))
                {
                    var path = new VertexStorage();
                    path.MoveTo(0, 0);
                    path.LineTo(width, 0);

                    var range = 360 / 4.0;
                    switch (Round)
                    {
                    case RoundTypes.Up:
                        for (int i = 1; i < roundSegments - 1; i++)
                        {
                            var angle = range / (roundSegments - 1) * i;
                            var rad   = MathHelper.DegreesToRadians(angle);
                            path.LineTo(Math.Cos(rad) * width, Math.Sin(rad) * height);
                        }
                        break;

                    case RoundTypes.Down:
                        for (int i = 1; i < roundSegments - 1; i++)
                        {
                            var angle = range / (roundSegments - 1) * i;
                            var rad   = MathHelper.DegreesToRadians(angle);
                            path.LineTo(width - Math.Sin(rad) * width, height - Math.Cos(rad) * height);
                        }
                        break;
                    }

                    path.LineTo(0, height);

                    Mesh = VertexSourceToMesh.Extrude(path, Depth.Value(this));
                    Mesh.Transform(Matrix4X4.CreateRotationX(MathHelper.Tau / 4));
                }
            }

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

            return(Task.CompletedTask);
        }
Example #10
0
        public void Vector3TransformByQuaternionTest()
        {
            Vector3D <float> v = new Vector3D <float>(1.0f, 2.0f, 3.0f);

            Matrix4X4 <float> m =
                Matrix4X4.CreateRotationX <float>(MathHelper.ToRadians(30.0f)) *
                Matrix4X4.CreateRotationY <float>(MathHelper.ToRadians(30.0f)) *
                Matrix4X4.CreateRotationZ <float>(MathHelper.ToRadians(30.0f));
            Quaternion <float> q = Quaternion <float> .CreateFromRotationMatrix(m);

            Vector3D <float> expected = Vector3D.Transform(v, m);
            Vector3D <float> actual   = Vector3D.Transform(v, q);

            Assert.True(MathHelper.Equal(expected, actual), "Vector3D<float>f.Transform did not return the expected value.");
        }
        public override void SetPosition(IObject3D selectedItem)
        {
            Vector3 boxCenter = GetControlCenter(selectedItem);
            double  distBetweenPixelsWorldSpace = InteractionContext.World.GetWorldUnitsPerScreenPixelAtPosition(boxCenter);

            GetCornerPosition(selectedItem, out int cornerIndexOut);

            Matrix4X4 centerMatrix = Matrix4X4.Identity;

            switch (RotationAxis)
            {
            case 0:
                if (cornerIndexOut == 1 || cornerIndexOut == 3)
                {
                    centerMatrix *= Matrix4X4.CreateRotationX(MathHelper.DegreesToRadians(90));
                }
                else
                {
                    centerMatrix *= Matrix4X4.CreateRotationY(MathHelper.DegreesToRadians(-90));
                }

                centerMatrix *= Matrix4X4.CreateRotationZ(MathHelper.DegreesToRadians(90) * cornerIndexOut);
                break;

            case 1:
                if (cornerIndexOut == 1 || cornerIndexOut == 3)
                {
                    centerMatrix *= Matrix4X4.CreateRotationY(MathHelper.DegreesToRadians(-90));
                }
                else
                {
                    centerMatrix *= Matrix4X4.CreateRotationX(MathHelper.DegreesToRadians(90));
                }

                centerMatrix *= Matrix4X4.CreateRotationZ(MathHelper.DegreesToRadians(90) * cornerIndexOut);
                break;

            case 2:
                centerMatrix *= Matrix4X4.CreateRotationZ(MathHelper.DegreesToRadians(90) * cornerIndexOut);
                break;
            }

            centerMatrix  *= Matrix4X4.CreateScale(distBetweenPixelsWorldSpace) * Matrix4X4.CreateTranslation(boxCenter);
            TotalTransform = centerMatrix;
        }
Example #12
0
        public void Vector3TransformNormalTest()
        {
            Vector3D <float>  v = new Vector3D <float>(1.0f, 2.0f, 3.0f);
            Matrix4X4 <float> m =
                Matrix4X4.CreateRotationX <float>(MathHelper.ToRadians(30.0f)) *
                Matrix4X4.CreateRotationY <float>(MathHelper.ToRadians(30.0f)) *
                Matrix4X4.CreateRotationZ <float>(MathHelper.ToRadians(30.0f));

            m.M41 = 10.0f;
            m.M42 = 20.0f;
            m.M43 = 30.0f;

            Vector3D <float> expected = new Vector3D <float>(2.19198728f, 1.53349364f, 2.61602545f);
            Vector3D <float> actual;

            actual = Vector3D.TransformNormal(v, m);
            Assert.True(MathHelper.Equal(expected, actual), "Vector3D<float>f.TransformNormal did not return the expected value.");
        }
Example #13
0
        public void Vector2TransformNormalTest()
        {
            Vector2D <float>  v = new Vector2D <float>(1.0f, 2.0f);
            Matrix4X4 <float> m =
                Matrix4X4.CreateRotationX <float>(MathHelper.ToRadians(30.0f)) *
                Matrix4X4.CreateRotationY <float>(MathHelper.ToRadians(30.0f)) *
                Matrix4X4.CreateRotationZ <float>(MathHelper.ToRadians(30.0f));

            m.M41 = 10.0f;
            m.M42 = 20.0f;
            m.M43 = 30.0f;

            Vector2D <float> expected = new Vector2D <float>(0.3169873f, 2.18301272f);
            Vector2D <float> actual;

            actual = Vector2D.TransformNormal(v, m);
            Assert.True(MathHelper.Equal(expected, actual), "Vector2f.Tranform did not return the expected value.");
        }
Example #14
0
        public void QuaternionFromRotationMatrixWithScaledMatrixTest3()
        {
            float             angle  = MathHelper.ToRadians(180.0f);
            Matrix4X4 <float> matrix = Matrix4X4.CreateRotationX <float>(angle) * Matrix4X4.CreateRotationY <float>(angle);

            Quaternion <float> expected = Quaternion <float> .CreateFromAxisAngle(Vector3D <float> .UnitY, angle) * Quaternion <float> .CreateFromAxisAngle(Vector3D <float> .UnitX, angle);

            Quaternion <float> actual = Quaternion <float> .CreateFromRotationMatrix(matrix);

            Assert.True(MathHelper.EqualRotation(expected, actual),
                        $"Quaternion<float>.CreateFromRotationMatrix did not return the expected value: expected {expected} actual {actual}");

            // make sure convert back to matrix is same as we passed matrix.
            Matrix4X4 <float> m2 = Matrix4X4.CreateFromQuaternion <float>(actual);

            Assert.True(MathHelper.Equal(matrix, m2),
                        $"Quaternion<float>.CreateFromQuaternion did not return the expected value: matrix {matrix} m2 {m2}");
        }
Example #15
0
        public void QuaternionFromRotationMatrixTest2()
        {
            for (float angle = 0.0f; angle < 720.0f; angle += 10.0f)
            {
                Matrix4X4 <float> matrix = Matrix4X4.CreateRotationX <float>(angle);

                Quaternion <float> expected = Quaternion <float> .CreateFromAxisAngle(Vector3D <float> .UnitX, angle);

                Quaternion <float> actual = Quaternion <float> .CreateFromRotationMatrix(matrix);

                Assert.True(MathHelper.EqualRotation(expected, actual),
                            $"Quaternion<float>.CreateFromRotationMatrix angle:{angle} did not return the expected value: expected {expected} actual {actual}");

                // make sure convert back to matrix is same as we passed matrix.
                Matrix4X4 <float> m2 = Matrix4X4.CreateFromQuaternion <float>(actual);
                Assert.True(MathHelper.Equal(matrix, m2),
                            $"Quaternion<float>.CreateFromQuaternion angle:{angle} did not return the expected value: matrix {matrix} m2 {m2}");
            }
        }
Example #16
0
        public override Task Rebuild()
        {
            this.DebugDepth("Rebuild");
            bool valuesChanged = false;

            RoundSegments = agg_basics.Clamp(RoundSegments, 3, 360 / 4 - 2, ref valuesChanged);

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

            using (RebuildLock())
            {
                using (new CenterAndHeightMaintainer(this))
                {
                    var path = new VertexStorage();
                    path.MoveTo(0, 0);
                    path.LineTo(Width, 0);

                    if (Round)
                    {
                        var range = 360 / 4.0;
                        for (int i = 1; i < RoundSegments - 1; i++)
                        {
                            var angle = range / (RoundSegments - 1) * i;
                            var rad   = MathHelper.DegreesToRadians(angle);
                            path.LineTo(Width - Math.Sin(rad) * Width, Height - Math.Cos(rad) * Height);
                        }
                    }

                    path.LineTo(0, Height);

                    Mesh = VertexSourceToMesh.Extrude(path, Depth);
                    Mesh.Transform(Matrix4X4.CreateRotationX(MathHelper.Tau / 4));
                }
            }

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

            return(Task.CompletedTask);
        }
Example #17
0
        public static async Task <CylinderObject3D> Create(double diameterBottom, double diameterTop, double height, int sides, Alignment alignment = Alignment.Z)
        {
            var item = new CylinderObject3D()
            {
                Advanced    = true,
                Diameter    = diameterBottom,
                DiameterTop = diameterTop,
                Height      = height,
                Sides       = sides,
            };

            await item.Rebuild();

            switch (alignment)
            {
            case Alignment.X:
                item.Matrix = Matrix4X4.CreateRotationY(MathHelper.Tau / 4);
                break;

            case Alignment.Y:
                item.Matrix = Matrix4X4.CreateRotationX(MathHelper.Tau / 4);
                break;

            case Alignment.Z:
                // This is the natural case (how it was modeled)
                break;

            case Alignment.negX:
                item.Matrix = Matrix4X4.CreateRotationY(-MathHelper.Tau / 4);
                break;

            case Alignment.negY:
                item.Matrix = Matrix4X4.CreateRotationX(-MathHelper.Tau / 4);
                break;

            case Alignment.negZ:
                item.Matrix = Matrix4X4.CreateRotationX(MathHelper.Tau / 2);
                break;
            }

            return(item);
        }
        override public Task Rebuild()
        {
            this.DebugDepth("Rebuild");
            using (RebuildLock())
            {
                using (new CenterAndHeightMantainer(this))
                {
                    var path = new VertexStorage();
                    path.MoveTo(0, 0);
                    path.LineTo(Width, 0);
                    path.LineTo(Width / 2, Height);

                    var mesh = VertexSourceToMesh.Extrude(path, Depth);
                    mesh.Transform(Matrix4X4.CreateRotationX(MathHelper.Tau / 4));
                    Mesh = mesh;
                }
            }

            Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Mesh));
            return(Task.CompletedTask);
        }
Example #19
0
        public override Task Rebuild()
        {
            this.DebugDepth("Rebuild");

            using (RebuildLock())
            {
                using (new CenterAndHeightMantainer(this))
                {
                    var startingAabb = this.GetAxisAlignedBoundingBox();
                    // remove whatever rotation has been applied (they go in reverse order)
                    Matrix = Matrix4X4.Identity;

                    // add the current rotation
                    Matrix = this.ApplyAtPosition(startingAabb.Center, Matrix4X4.CreateRotationX(MathHelper.DegreesToRadians(RotationXDegrees)));
                    Matrix = this.ApplyAtPosition(startingAabb.Center, Matrix4X4.CreateRotationY(MathHelper.DegreesToRadians(RotationYDegrees)));
                    Matrix = this.ApplyAtPosition(startingAabb.Center, Matrix4X4.CreateRotationZ(MathHelper.DegreesToRadians(RotationZDegrees)));
                }
            }

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

            return(Task.CompletedTask);
        }
        public void Rebuild(UndoBuffer undoBuffer)
        {
            using (RebuildLock())
            {
                var aabb = this.GetAxisAlignedBoundingBox();

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

                var brailleLetter = new BrailleObject3D()
                {
                    TextToEncode = Letter.ToString(),
                    BaseHeight   = BaseHeight,
                };
                brailleLetter.Rebuild(null);
                this.Children.Add(brailleLetter);

                var textObject = new TextObject3D()
                {
                    PointSize   = 46,
                    Color       = Color.LightBlue,
                    NameToWrite = Letter.ToString(),
                    Height      = BaseHeight
                };

                textObject.Invalidate(new InvalidateArgs(textObject, InvalidateType.Properties, null));
                IObject3D letterObject = new RotateObject3D(textObject, MathHelper.Tau / 4);
                letterObject = new AlignObject3D(letterObject, FaceAlign.Bottom | FaceAlign.Front, brailleLetter, FaceAlign.Top | FaceAlign.Front, 0, 0, 3.5);
                letterObject = new SetCenterObject3D(letterObject, brailleLetter.GetCenter(), true, false, false);
                this.Children.Add(letterObject);

                var basePath = new RoundedRect(0, 0, 22, 34, 3)
                {
                    ResolutionScale = 10
                };

                IObject3D basePlate = new Object3D()
                {
                    Mesh   = VertexSourceToMesh.Extrude(basePath, BaseHeight),
                    Matrix = Matrix4X4.CreateRotationX(MathHelper.Tau / 4)
                };

                basePlate = new AlignObject3D(basePlate, FaceAlign.Bottom | FaceAlign.Back, brailleLetter, FaceAlign.Bottom | FaceAlign.Back);
                basePlate = new SetCenterObject3D(basePlate, brailleLetter.GetCenter(), true, false, false);
                this.Children.Add(basePlate);

                IObject3D underline = new CubeObject3D(basePlate.XSize(), .2, 1);
                underline = new AlignObject3D(underline, FaceAlign.Bottom, brailleLetter, FaceAlign.Top);
                underline = new AlignObject3D(underline, FaceAlign.Back | FaceAlign.Left, basePlate, FaceAlign.Front | FaceAlign.Left, 0, .01);
                this.Children.Add(underline);

                if (aabb.ZSize > 0)
                {
                    // If the part was already created and at a height, maintain the height.
                    PlatingHelper.PlaceMeshAtHeight(this, aabb.minXYZ.Z);
                }
            }

            Invalidate(new InvalidateArgs(this, InvalidateType.Content));
        }
        public static Mesh Revolve(this IVertexSource source,
                                   int angleSteps      = 30,
                                   double angleStart   = 0,
                                   double angleEnd     = MathHelper.Tau,
                                   bool revolveAroundZ = true)
        {
            angleStart = MathHelper.Range0ToTau(angleStart);
            angleEnd   = MathHelper.Range0ToTau(angleEnd);

            // make sure we close 360 shapes
            angleStart = fixCloseAngles(angleStart);
            angleEnd   = fixCloseAngles(angleEnd);

            if (angleStart == 0 && angleEnd == MathHelper.Tau)
            {
                angleSteps = Math.Max(angleSteps, 3);
            }
            else
            {
                angleSteps = Math.Max(angleSteps, 1);
            }

            // convert to clipper polygons and scale so we can ensure good shapes
            Polygons polygons = source.CreatePolygons();

            if (polygons.Select(poly => poly.Where(pos => pos.X < 0)).Any())
            {
                // ensure good winding and consistent shapes
                polygons = polygons.GetCorrectedWinding();
                var bounds = polygons.GetBounds();
                bounds.Inflate(10);
                // clip against x=0 left and right
                var leftClip = new Polygon();
                leftClip.Add(new IntPoint(0, bounds.Bottom));
                leftClip.Add(new IntPoint(0, bounds.Top));
                leftClip.Add(new IntPoint(bounds.Left, bounds.Top));
                leftClip.Add(new IntPoint(bounds.Left, bounds.Bottom));
                var rightStuff = polygons.Subtract(leftClip);

                var rightClip = new Polygon();
                rightClip.Add(new IntPoint(0, bounds.Top));
                rightClip.Add(new IntPoint(0, bounds.Bottom));
                rightClip.Add(new IntPoint(bounds.Right, bounds.Bottom));
                rightClip.Add(new IntPoint(bounds.Right, bounds.Top));
                var leftStuff = polygons.Subtract(rightClip);
                // mirror left material across the origin
                var leftAdd = leftStuff.Scale(-1, 1);
                if (leftAdd.Count > 0)
                {
                    if (rightStuff.Count > 0)
                    {
                        polygons = rightStuff.Union(leftAdd);
                    }
                    else
                    {
                        polygons = leftAdd;
                    }
                }
                else
                {
                    // there is nothing on the left
                    polygons = rightStuff;
                }
            }

            // convert the data back to PathStorage
            VertexStorage cleanedPath = polygons.CreateVertexStorage();

            var mesh = new Mesh();

            var hasStartAndEndFaces = angleStart > 0.000001;

            hasStartAndEndFaces |= angleEnd < MathHelper.Tau - 0.000001;
            // check if we need to make closing faces
            if (hasStartAndEndFaces)
            {
                // make a face for the start
                Mesh extrudedVertexSource = cleanedPath.TriangulateFaces();
                if (revolveAroundZ)
                {
                    extrudedVertexSource.Transform(Matrix4X4.CreateRotationX(MathHelper.Tau / 4));
                    extrudedVertexSource.Transform(Matrix4X4.CreateRotationZ(angleStart));
                }
                else
                {
                    extrudedVertexSource.Transform(Matrix4X4.CreateRotationY(angleStart));
                }

                mesh.CopyFaces(extrudedVertexSource);
            }

            // make the outside shell
            double angleDelta   = (angleEnd - angleStart) / angleSteps;
            double currentAngle = angleStart;

            if (!hasStartAndEndFaces)
            {
                angleSteps--;
            }

            for (int i = 0; i < angleSteps; i++)
            {
                AddRevolveStrip(cleanedPath, mesh, currentAngle, currentAngle + angleDelta, revolveAroundZ);
                currentAngle += angleDelta;
            }

            if (!hasStartAndEndFaces)
            {
                if (((angleEnd - angleStart) < .0000001 ||
                     (angleEnd - MathHelper.Tau - angleStart) < .0000001) &&
                    (angleEnd - currentAngle) > .0000001)
                {
                    // make sure we close the shape exactly
                    AddRevolveStrip(cleanedPath, mesh, currentAngle, angleStart, revolveAroundZ);
                }
            }
            else             // add the end face
            {
                // make a face for the end
                Mesh extrudedVertexSource = cleanedPath.TriangulateFaces();
                if (revolveAroundZ)
                {
                    extrudedVertexSource.Transform(Matrix4X4.CreateRotationX(MathHelper.Tau / 4));
                    extrudedVertexSource.Transform(Matrix4X4.CreateRotationZ(currentAngle));
                }
                else
                {
                    extrudedVertexSource.Transform(Matrix4X4.CreateRotationY(angleStart));
                }

                extrudedVertexSource.ReverseFaces();
                mesh.CopyFaces(extrudedVertexSource);
            }

            mesh.CleanAndMerge();

            // return the completed mesh
            return(mesh);
        }
Example #22
0
        private void Rebuild(UndoBuffer undoBuffer)
        {
            this.DebugDepth("Rebuild");
            bool propertyUpdated = Diameter == double.MinValue;

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

            using (RebuildLock())
            {
                ResetMeshWrapperMeshes(Object3DPropertyFlags.All, CancellationToken.None);

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

                var meshWrapperEnumerator = WrappedObjects();

                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;
                    rotationCenter = new Vector2(aabb.minXYZ.X + (aabb.maxXYZ.X - aabb.minXYZ.X) * (StartPercent / 100), aabb.maxXYZ.Y + radius);
                    foreach (var object3Ds in meshWrapperEnumerator)
                    {
                        var originalMatrix = object3Ds.original.WorldMatrix(this);
                        var curvedMesh     = object3Ds.meshCopy.Mesh;
                        var originalMesh   = object3Ds.original.Mesh;

                        if (false)
                        {
                            int    sidesPerRotation = 30;
                            double numRotations     = aabb.XSize / circumference;
                            double numberOfCuts     = numRotations * sidesPerRotation;
                            var    maxXLength       = aabb.XSize / numberOfCuts;
                            // chop any segment that is too short in x
                            for (int i = curvedMesh.MeshEdges.Count - 1; i >= 0; i--)
                            {
                                var edgeToSplit     = curvedMesh.MeshEdges[i];
                                var start           = edgeToSplit.VertexOnEnd[0].Position;
                                var end             = edgeToSplit.VertexOnEnd[1].Position;
                                var edgeXLength     = Math.Abs(end.X - start.X);
                                int numberOfDivides = (int)(edgeXLength / maxXLength);
                                if (numberOfDivides > 1)
                                {
                                    for (int j = 1; j < numberOfDivides - 1; j++)
                                    {
                                        IVertex  newVertex;
                                        MeshEdge newMeshEdge;
                                        curvedMesh.SplitMeshEdge(edgeToSplit, out newVertex, out newMeshEdge);
                                        var otherIndex = newMeshEdge.GetVertexEndIndex(newVertex);
                                        var ratio      = (numberOfDivides - j) / (double)numberOfDivides;
                                        newVertex.Position = start + (end - start) * ratio;
                                        edgeToSplit        = newMeshEdge;
                                        start = edgeToSplit.VertexOnEnd[0].Position;
                                        end   = edgeToSplit.VertexOnEnd[1].Position;

                                        foreach (var face in edgeToSplit.FacesSharingMeshEdge())
                                        {
                                            Face newFace;
                                            curvedMesh.SplitFace(face,
                                                                 edgeToSplit.VertexOnEnd[0],
                                                                 edgeToSplit.VertexOnEnd[1],
                                                                 out newMeshEdge,
                                                                 out newFace);
                                        }
                                    }
                                }
                            }
                        }

                        for (int i = 0; i < originalMesh.Vertices.Count; i++)
                        {
                            var matrix = originalMatrix;
                            if (!BendCcw)
                            {
                                // rotate around so it will bend correctly
                                matrix *= Matrix4X4.CreateTranslation(0, -aabb.maxXYZ.Y, 0);
                                matrix *= Matrix4X4.CreateRotationX(MathHelper.Tau / 2);
                                matrix *= Matrix4X4.CreateTranslation(0, aabb.maxXYZ.Y - aabb.YSize, 0);
                            }
                            var worldPosition = Vector3.Transform(originalMesh.Vertices[i].Position, matrix);

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

                            var rotatePosition = new Vector3(Math.Cos(angleToRotate), Math.Sin(angleToRotate), 0) * distanceFromCenter;
                            rotatePosition.Z = worldPosition.Z;
                            var worldWithBend = rotatePosition + new Vector3(rotationCenter.X, radius + aabb.maxXYZ.Y, 0);
                            curvedMesh.Vertices[i].Position = Vector3.Transform(worldWithBend, matrix.Inverted);
                        }

                        // the vertices need to be resorted as they have moved relative to each other
                        curvedMesh.Vertices.Sort();

                        curvedMesh.MarkAsChanged();
                        curvedMesh.CalculateNormals();
                    }

                    if (!BendCcw)
                    {
                        // fix the stored center so we draw correctly
                        rotationCenter = new Vector2(rotationCenter.X, aabb.minXYZ.Y - radius);
                    }
                }

                // set the matrix back
                Matrix = currentMatrix;
            }

            base.OnInvalidate(new InvalidateArgs(this, InvalidateType.Mesh));
            if (propertyUpdated)
            {
                base.OnInvalidate(new InvalidateArgs(this, InvalidateType.Properties));
            }
        }
Example #23
0
        private static World CreateWorld()
        {
            var floor = new Sphere(Matrix4X4.CreateScale(10, 0.01, 10))
            {
                Material = new Material
                {
                    Color = new Color(1, 0.9, 0.9),
                    Specular = 0,
                }
            };

            var leftWall = new Sphere(Matrix4X4.CreateTranslation(0, 0, 5) *
                                      Matrix4X4.CreateRotationY(-Math.PI / 4) *
                                      Matrix4X4.CreateRotationX(Math.PI / 2) *
                                      Matrix4X4.CreateScale(10, 0.01, 10))
            {
                Material = new Material
                {
                    Color = new Color(1, 0.9, 0.9),
                    Specular = 0,
                }
            };

            var rightWall = new Sphere(Matrix4X4.CreateTranslation(0, 0, 5) *
                                       Matrix4X4.CreateRotationY(Math.PI / 4) *
                                       Matrix4X4.CreateRotationX(Math.PI / 2) *
                                       Matrix4X4.CreateScale(10, 0.01, 10))
            {
                Material = new Material
                {
                    Color = new Color(1, 0.9, 0.9),
                    Specular = 0,
                }
            };

            var middleSphere = new Sphere(Matrix4X4.CreateTranslation(-0.5, 1, 0.5))
            {
                Material = new Material
                {
                    Color = new Color(0.1, 1, 0.5),
                    Diffuse = 0.7,
                    Specular = 0.3,
                }
            };

            var rightSphere = new Sphere(Matrix4X4.CreateTranslation(1.5, 0.5, -0.5) *
                                         Matrix4X4.CreateScale(0.5, 0.5, 0.5))
            {
                Material = new Material
                {
                    Color = new Color(0.5, 1, 0.1),
                    Diffuse = 0.7,
                    Specular = 0.3,
                }
            };

            var leftSphere = new Sphere(Matrix4X4.CreateTranslation(-1.5, 0.33, -0.75) *
                                        Matrix4X4.CreateScale(0.33, 0.33, 0.33))
            {
                Material = new Material
                {
                    Color = new Color(1, 0.8, 0.1),
                    Diffuse = 0.7,
                    Specular = 0.3,
                }
            };
            
            var light = new PointLight(new Point(-10, 10, -10), new Color(1, 1, 1));

            return new World
            {
                Objects = {floor, rightWall, leftWall, middleSphere, rightSphere, leftSphere},
                PointLights = {light},
            };
        }
Example #24
0
        public void RotateRelative(double x, double y, double z)
        {
#if true
            if (x != 0)
            {
                Matrix4X4 M1 = Matrix4X4.Identity;
                M1 = Matrix4X4.CreateRotationX(x);
                if (y != 0)
                {
                    Matrix4X4 M2 = Matrix4X4.Identity;
                    Matrix4X4 M4 = Matrix4X4.Identity;
                    M2 = Matrix4X4.CreateRotationY(y);
                    M4 = M2 * M1;
                    if (z != 0)
                    {
                        Matrix4X4 M3 = Matrix4X4.Identity;
                        M3 = Matrix4X4.CreateRotationZ(z);
                        Matrix4X4 Delta = Matrix4X4.Identity;
                        Delta        = M3 * M4;
                        AxisToWorld *= Delta;
                    }
                    else
                    {
                        AxisToWorld *= M4;
                    }
                }
                else
                {
                    if (z != 0)
                    {
                        Matrix4X4 M3 = Matrix4X4.Identity;
                        M3 = Matrix4X4.CreateRotationZ(z);
                        Matrix4X4 Delta = Matrix4X4.Identity;
                        Delta        = M3 * M1;
                        AxisToWorld *= Delta;
                    }
                    else
                    {
                        AxisToWorld *= M1;
                    }
                }
            }
            else
            {
                if (y != 0)
                {
                    Matrix4X4 M2 = Matrix4X4.Identity;
                    M2 = Matrix4X4.CreateRotationY(y);
                    if (z != 0)
                    {
                        Matrix4X4 M3 = Matrix4X4.Identity;
                        M3 = Matrix4X4.CreateRotationZ(z);
                        Matrix4X4 Delta = Matrix4X4.Identity;
                        Delta        = M3 * M2;
                        AxisToWorld *= Delta;
                    }
                    else
                    {
                        AxisToWorld *= M2;
                    }
                }
                else
                {
                    if (z != 0)
                    {
                        Matrix4X4 M3 = Matrix4X4.Identity;
                        M3           = Matrix4X4.CreateRotationZ(z);
                        AxisToWorld *= M3;
                    }
                }
            }

            WorldToAxis = Matrix4X4.Invert(AxisToWorld);
#else
            M1.Rotate(0, x);
            M2.Rotate(1, y);
            M3.Rotate(2, z);
            // 1 * 2 * 3
            M4    = M2 * M1;
            Delta = M3 * M4;

            AxisToWorld = AxisToWorld * Delta;

            WorldToAxis = AxisToWorld.GetInverse();
#endif
        }
        public static Mesh Revolve(IVertexSource source, int angleSteps = 30, double angleStart = 0, double angleEnd = MathHelper.Tau)
        {
            angleSteps = Math.Max(angleSteps, 3);
            angleStart = MathHelper.Range0ToTau(angleStart);
            angleEnd   = MathHelper.Range0ToTau(angleEnd);
            // convert to clipper polygons and scale so we can ensure good shapes
            Polygons polygons = source.CreatePolygons();
            // ensure good winding and consistent shapes
            // clip against x=0 left and right
            // mirror left material across the origin
            // union mirrored left with right material
            // convert the data back to PathStorage
            VertexStorage cleanedPath = polygons.CreateVertexStorage();

            Mesh mesh = new Mesh();

            var hasStartAndEndFaces = angleStart > 0.000001;

            hasStartAndEndFaces |= angleEnd < MathHelper.Tau - 0.000001;
            // check if we need to make closing faces
            if (hasStartAndEndFaces)
            {
                // make a face for the start
                CachedTesselator teselatedSource      = new CachedTesselator();
                Mesh             extrudedVertexSource = TriangulateFaces(source, teselatedSource);
                extrudedVertexSource.Transform(Matrix4X4.CreateRotationX(MathHelper.Tau / 4));
                extrudedVertexSource.Transform(Matrix4X4.CreateRotationZ(angleStart));
                mesh.CopyFaces(extrudedVertexSource);
            }

            // make the outside shell
            double angleDelta   = (angleEnd - angleStart) / angleSteps;
            double currentAngle = angleStart;

            if (!hasStartAndEndFaces)
            {
                angleSteps--;
            }

            for (int i = 0; i < angleSteps; i++)
            {
                AddRevolveStrip(cleanedPath, mesh, currentAngle, currentAngle + angleDelta);
                currentAngle += angleDelta;
            }

            if (!hasStartAndEndFaces)
            {
                if (((angleEnd - angleStart) < .0000001 ||
                     (angleEnd - MathHelper.Tau - angleStart) < .0000001) &&
                    (angleEnd - currentAngle) > .0000001)
                {
                    // make sure we close the shape exactly
                    AddRevolveStrip(cleanedPath, mesh, currentAngle, angleStart);
                }
            }
            else             // add the end face
            {
                // make a face for the end
                CachedTesselator teselatedSource      = new CachedTesselator();
                Mesh             extrudedVertexSource = TriangulateFaces(source, teselatedSource);
                extrudedVertexSource.Transform(Matrix4X4.CreateRotationX(MathHelper.Tau / 4));
                extrudedVertexSource.Transform(Matrix4X4.CreateRotationZ(currentAngle));
                extrudedVertexSource.ReverseFaceEdges();
                mesh.CopyFaces(extrudedVertexSource);
            }

            // return the completed mesh
            return(mesh);
        }
Example #26
0
        public override async Task Rebuild()
        {
            using (RebuildLock())
            {
                using (new CenterAndHeightMantainer(this))
                {
                    this.Children.Modify(list =>
                    {
                        list.Clear();
                    });

                    var brailleLetter = new BrailleObject3D()
                    {
                        TextToEncode = Letter.ToString(),
                        BaseHeight   = BaseHeight,
                    };
                    await brailleLetter.Rebuild();

                    this.Children.Add(brailleLetter);

                    var textObject = new TextObject3D()
                    {
                        PointSize   = 46,
                        Color       = Color.LightBlue,
                        NameToWrite = Letter.ToString(),
                        Height      = BaseHeight
                    };

                    await textObject.Rebuild();

                    IObject3D letterObject = new RotateObject3D_2(textObject, Vector3.UnitX, -90);
                    await letterObject.Rebuild();

                    var scaleRatio = Math.Max(letterObject.XSize() / 17, letterObject.ZSize() / 17);
                    if (scaleRatio > 1)
                    {
                        letterObject = new ScaleObject3D(letterObject, 1.0 / scaleRatio, 1, 1.0 / scaleRatio);
                    }
                    letterObject = new AlignObject3D(letterObject, FaceAlign.Bottom | FaceAlign.Front, brailleLetter, FaceAlign.Top | FaceAlign.Front, 0, 0, 3.5);
                    letterObject = new SetCenterObject3D(letterObject, brailleLetter.GetCenter(), true, false, false);
                    this.Children.Add(letterObject);

                    var basePath = new RoundedRect(0, 0, 22, 34, 3)
                    {
                        ResolutionScale = 10
                    };

                    IObject3D basePlate = new Object3D()
                    {
                        Mesh   = VertexSourceToMesh.Extrude(basePath, BaseHeight),
                        Matrix = Matrix4X4.CreateRotationX(MathHelper.Tau / 4)
                    };

                    basePlate = new AlignObject3D(basePlate, FaceAlign.Bottom | FaceAlign.Back, brailleLetter, FaceAlign.Bottom | FaceAlign.Back);
                    basePlate = new SetCenterObject3D(basePlate, brailleLetter.GetCenter(), true, false, false);
                    this.Children.Add(basePlate);

                    IObject3D underline = await CubeObject3D.Create(basePlate.XSize(), .2, 1);

                    underline = new AlignObject3D(underline, FaceAlign.Bottom, brailleLetter, FaceAlign.Top);
                    underline = new AlignObject3D(underline, FaceAlign.Back | FaceAlign.Left, basePlate, FaceAlign.Front | FaceAlign.Left, 0, .01);
                    this.Children.Add(underline);
                }
            }

            Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Children));
        }
Example #27
0
        public override Task Rebuild()
        {
            this.DebugDepth("Rebuild");
            bool valuesChanged = Diameter == double.MinValue;

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

            using (RebuildLock())
            {
                ResetMeshWrapperMeshes(Object3DPropertyFlags.All, CancellationToken.None);

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

                var meshWrapperEnumerator = WrappedObjects();

                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;
                    rotationCenter = new Vector2(aabb.MinXYZ.X + (aabb.MaxXYZ.X - aabb.MinXYZ.X) * (StartPercent / 100), aabb.MaxXYZ.Y + radius);
                    foreach (var object3Ds in meshWrapperEnumerator)
                    {
                        var matrix = object3Ds.original.WorldMatrix(this);
                        if (!BendCcw)
                        {
                            // rotate around so it will bend correctly
                            matrix *= Matrix4X4.CreateTranslation(0, -aabb.MaxXYZ.Y, 0);
                            matrix *= Matrix4X4.CreateRotationX(MathHelper.Tau / 2);
                            matrix *= Matrix4X4.CreateTranslation(0, aabb.MaxXYZ.Y - aabb.YSize, 0);
                        }

                        var matrixInv = matrix.Inverted;

                        var curvedMesh = object3Ds.meshCopy.Mesh;

                        // split long edges so it will be curved
                        if (false)
                        {
                            double numRotations   = aabb.XSize / circumference;
                            double numberOfCuts   = numRotations * MinSidesPerRotation;
                            var    maxXLength     = aabb.XSize / numberOfCuts;
                            var    maxXLengthSqrd = maxXLength * maxXLength;

                            // convert the mesh into vertex and face arrays
                            double[] v;
                            int[]    f;
                            v = curvedMesh.Vertices.ToDoubleArray(object3Ds.meshCopy.Matrix);
                            f = curvedMesh.Faces.ToIntArray();

                            // make lists so we can add to them
                            var vL = v.ToVector3List();
                            vL.Transform(matrix);
                            var fL = new FaceList(f, curvedMesh.Vertices);

                            Teselate.SplitEdges(vL, fL, maxXLength);
                            vL.Transform(matrixInv);

                            // convert the lists back into the mesh
                            object3Ds.meshCopy.Mesh = new Mesh(vL, fL);
                            curvedMesh = object3Ds.meshCopy.Mesh;
                        }

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

                            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);
                            curvedMesh.Vertices[i] = worldWithBend.Transform(matrixInv);
                        }

                        curvedMesh.MarkAsChanged();
                        curvedMesh.CalculateNormals();
                    }

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

                // set the matrix back
                Matrix = currentMatrix;
            }

            Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Mesh));
            if (valuesChanged)
            {
                Invalidate(InvalidateType.DisplayValues);
            }

            return(Task.CompletedTask);
        }
Example #28
0
        override public Task Rebuild()
        {
            using (RebuildLock())
            {
                using (new CenterAndHeightMantainer(this))
                {
                    this.Children.Modify(list =>
                    {
                        list.Clear();
                    });

                    var brailleText = TextToEncode;
                    if (UseGrade2)
                    {
                        brailleText = BrailleGrade2.ConvertString(brailleText);
                    }

                    double    pointSize  = 18.5;
                    double    pointsToMm = 0.352778;
                    IObject3D textObject = new Object3D();
                    var       offest     = 0.0;

                    TypeFacePrinter textPrinter;
                    if (RenderAsBraille)
                    {
                        textPrinter = new TypeFacePrinter(brailleText, new StyledTypeFace(typeFace, pointSize));
                    }
                    else
                    {
                        textPrinter = new TypeFacePrinter(brailleText, new StyledTypeFace(ApplicationController.GetTypeFace(NamedTypeFace.Liberation_Mono), pointSize));
                    }

                    foreach (var letter in brailleText.ToCharArray())
                    {
                        IObject3D       letterObject;
                        TypeFacePrinter letterPrinter;
                        if (RenderAsBraille)
                        {
                            letterPrinter = new TypeFacePrinter(letter.ToString(), new StyledTypeFace(typeFace, pointSize));
                            var scalledLetterPrinter = new VertexSourceApplyTransform(letterPrinter, Affine.NewScaling(pointsToMm));

                            // add all the spheres to letterObject
                            letterObject = new Object3D();

                            var vertexCount  = 0;
                            var positionSum  = Vector2.Zero;
                            var lastPosition = Vector2.Zero;
                            // find each dot outline and get it's center and place a sphere there
                            foreach (var vertex in scalledLetterPrinter.Vertices())
                            {
                                switch (vertex.command)
                                {
                                case Agg.ShapePath.FlagsAndCommand.Stop:
                                case Agg.ShapePath.FlagsAndCommand.EndPoly:
                                case Agg.ShapePath.FlagsAndCommand.FlagClose:
                                case Agg.ShapePath.FlagsAndCommand.MoveTo:
                                    if (vertexCount > 0)
                                    {
                                        var    center = positionSum / vertexCount;
                                        double radius = 1.44 / 2;                                                // (center - lastPosition).Length;
                                        var    sphere = new HalfSphereObject3D(radius * 2, 15)
                                        {
                                            Color = Color.LightBlue
                                        };
                                        sphere.Translate(center.X, center.Y);
                                        letterObject.Children.Add(sphere);
                                    }
                                    vertexCount = 0;
                                    positionSum = Vector2.Zero;
                                    break;

                                case Agg.ShapePath.FlagsAndCommand.Curve3:
                                case Agg.ShapePath.FlagsAndCommand.Curve4:
                                case Agg.ShapePath.FlagsAndCommand.LineTo:
                                    vertexCount++;
                                    lastPosition = vertex.position;
                                    positionSum += lastPosition;
                                    break;
                                }
                            }
                        }
                        else
                        {
                            letterPrinter = new TypeFacePrinter(letter.ToString(), new StyledTypeFace(ApplicationController.GetTypeFace(NamedTypeFace.Liberation_Mono), pointSize));
                            var scalledLetterPrinter = new VertexSourceApplyTransform(letterPrinter, Affine.NewScaling(pointsToMm));
                            letterObject = new Object3D()
                            {
                                Mesh  = VertexSourceToMesh.Extrude(scalledLetterPrinter, 1),
                                Color = Color.LightBlue
                            };
                        }

                        letterObject.Matrix = Matrix4X4.CreateTranslation(offest, 0, 0);
                        textObject.Children.Add(letterObject);

                        offest += letterPrinter.GetSize(letter.ToString()).X *pointsToMm;
                    }

                    // add a plate under the dots
                    var padding = .9 * pointSize * pointsToMm / 2;
                    var size    = textPrinter.LocalBounds * pointsToMm;

                    // make the base
                    var basePath = new VertexStorage();
                    basePath.MoveTo(0, 0);
                    basePath.LineTo(size.Width + padding, 0);
                    basePath.LineTo(size.Width + padding, size.Height + padding);
                    basePath.LineTo(padding, size.Height + padding);
                    basePath.LineTo(0, size.Height);

                    IObject3D basePlate = new Object3D()
                    {
                        Mesh = VertexSourceToMesh.Extrude(basePath, BaseHeight)
                    };

                    basePlate = new AlignObject3D(basePlate, FaceAlign.Top, textObject, FaceAlign.Bottom, 0, 0, .01);
                    basePlate = new AlignObject3D(basePlate, FaceAlign.Left | FaceAlign.Front,
                                                  size.Left - padding / 2,
                                                  size.Bottom - padding / 2);
                    this.Children.Add(basePlate);

                    basePlate.Matrix *= Matrix4X4.CreateRotationX(MathHelper.Tau / 4);

                    // add an optional chain hook
                    if (AddHook)
                    {
                        // x 10 to make it smoother
                        double        edgeWidth      = 3;
                        double        height         = basePlate.ZSize();
                        IVertexSource leftSideObject = new RoundedRect(0, 0, height / 2, height, 0)
                        {
                            ResolutionScale = 10
                        };

                        IVertexSource cicleObject = new Ellipse(0, 0, height / 2, height / 2)
                        {
                            ResolutionScale = 10
                        };

                        cicleObject = new Align2D(cicleObject, Side2D.Left | Side2D.Bottom, leftSideObject, Side2D.Left | Side2D.Bottom, -.01);
                        IVertexSource holeObject = new Ellipse(0, 0, height / 2 - edgeWidth, height / 2 - edgeWidth)
                        {
                            ResolutionScale = 10
                        };
                        holeObject = new SetCenter2D(holeObject, cicleObject.GetBounds().Center);

                        IVertexSource hookPath = leftSideObject.Plus(cicleObject);
                        hookPath = hookPath.Minus(holeObject);

                        IObject3D chainHook = new Object3D()
                        {
                            Mesh   = VertexSourceToMesh.Extrude(hookPath, BaseHeight),
                            Matrix = Matrix4X4.CreateRotationX(MathHelper.Tau / 4)
                        };

                        chainHook = new AlignObject3D(chainHook, FaceAlign.Left | FaceAlign.Bottom | FaceAlign.Back, basePlate, FaceAlign.Right | FaceAlign.Bottom | FaceAlign.Back, -.01);

                        this.Children.Add(chainHook);
                    }

                    // add the object that is the dots
                    this.Children.Add(textObject);
                    textObject.Matrix *= Matrix4X4.CreateRotationX(MathHelper.Tau / 4);
                }
            }

            Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Children));
            return(Task.CompletedTask);
        }
Example #29
0
        private static World CreateWorld()
        {
            var floor = new Plane
            {
                Material = new Material
                {
                    Pattern  = new CheckersPattern(Color.White, Color.Black),
                    Color    = Color.White,
                    Specular = 0,
                }
            };

            var backWall = new Plane
            {
                TransformMatrix = new Transform().RotateX(Math.PI / 2)
                                  .RotateY(-Math.PI / 2)
                                  .Translate(1.5, 0, 0)
                                  .GetTransformationMatrix(),

                Material = new Material
                {
                    Pattern = new StripePattern(new Color(0, 0.5, 0.5), new Color(1, 0, 0))
                    {
                        TransformMatrix = Matrix4X4.CreateRotationY(Math.PI / 4)
                    },
                    Specular = 0,
                }
            };

            var middleSphere = new Sphere(Matrix4X4.CreateTranslation(-0.5, 1, 0.5))
            {
                Material = new Material
                {
                    Pattern = new RingPattern(new Color(1, 0, 0), new Color(0, 1, 0))
                    {
                        TransformMatrix = Matrix4X4.CreateRotationX(Math.PI / -3) *
                                          Matrix4X4.CreateScale(0.25, 0.25, 0.25)
                    },
                    Diffuse  = 0.7,
                    Specular = 0.3,
                }
            };

            var rightSphere = new Sphere(Matrix4X4.CreateTranslation(1.5, 0.5, -0.5) *
                                         Matrix4X4.CreateScale(0.5, 0.5, 0.5))
            {
                Material = new Material
                {
                    Color    = new Color(0.5, 1, 0.1),
                    Diffuse  = 0.7,
                    Specular = 0.3,
                }
            };

            var leftSphere = new Sphere(Matrix4X4.CreateTranslation(-1.5, 0.33, -0.75) *
                                        Matrix4X4.CreateScale(0.33, 0.33, 0.33))
            {
                Material = new Material
                {
                    Pattern = new StripePattern(new Color(0, 0, 1), new Color(0, 1, 0))
                    {
                        TransformMatrix = Matrix4X4.CreateScale(0.25, 0.25, 0.25)
                    },
                    Diffuse  = 0.7,
                    Specular = 0.3,
                }
            };

            var light = new PointLight(new Point(-10, 10, -10), new Color(1, 1, 1));

            return(new World
            {
                Objects = { middleSphere, rightSphere, leftSphere, floor, backWall },
                PointLights = { light },
            });
        }
        public override Task Rebuild()
        {
            // Point Size 10
            // Height 1
            // Font Fredoka

            // Align
            // X: Right Right -11
            // Y: Front -.3
            // Z: Bottom .8

            this.DebugDepth("Rebuild");
            bool valuesChanged = false;

            using (RebuildLock())
            {
                MaxTemperature = agg_basics.Clamp(MaxTemperature, 140, 400, ref valuesChanged);
                Sections       = agg_basics.Clamp(Sections, 2, 20, ref valuesChanged);
                ChangeAmount   = agg_basics.Clamp(ChangeAmount, 1, 30, ref valuesChanged);

                using (new CenterAndHeightMaintainer(this))
                {
                    Children.Modify(async(children) =>
                    {
                        children.Clear();

                        // add the base
                        var towerBase = new Object3D()
                        {
                            Mesh = new RoundedRect(-25, -15, 25, 15, 3)
                            {
                                ResolutionScale = 10
                            }.Extrude(BaseHeight),
                            Name = "Base"
                        };

                        children.Add(towerBase);

                        // Add each section
                        for (int i = 0; i < Sections; i++)
                        {
                            var temp    = MaxTemperature - i * ChangeAmount;
                            var section = new Object3D()
                            {
                                Matrix = Matrix4X4.CreateTranslation(0, 0, BaseHeight + i * SectionHeight),
                                Name   = $"{temp:0.##}"
                            };
                            children.Add(section);
                            // Add base mesh
                            section.Children.Add(new Object3D()
                            {
                                Mesh = shape,
                                Name = "CC - gaaZolee - AS"
                            });
                            // Add temp changer
                            section.Children.Add(new SetTemperatureObject3D()
                            {
                                Temperature = temp,
                                Name        = $"Set to {temp:0.##}",
                                Matrix      = Matrix4X4.CreateScale(.2, .1, 1)
                            });
                            // Add temperature text
                            var text = new TextObject3D()
                            {
                                Font        = NamedTypeFace.Fredoka,
                                Height      = 1,
                                Name        = $"{temp:0.##}",
                                PointSize   = 10,
                                NameToWrite = $"{temp:0.##}",
                                Matrix      = Matrix4X4.CreateRotationX(MathHelper.Tau / 4) * Matrix4X4.CreateTranslation(0, -4.3, .8),
                            };
                            text.Rebuild().Wait();
                            var textBounds = text.GetAxisAlignedBoundingBox();
                            text.Matrix   *= Matrix4X4.CreateTranslation(11 - textBounds.MaxXYZ.X, 0, 0);
                            section.Children.Add(text);
                        }
                    });
                }
            }

            Invalidate(InvalidateType.DisplayValues);

            Parent?.Invalidate(new InvalidateArgs(this, InvalidateType.Mesh));
            return(Task.CompletedTask);
        }