Пример #1
0
        public IEnumerable <IMapObject> Create(UniqueNumberGenerator generator, Box box, string texture, int roundDecimals)
        {
            var useCentroid = _useCentroid.GetValue();

            // The lower Z plane will be the triangle, with the lower Y value getting the two corners
            var c1       = new Vector3(box.Start.X, box.Start.Y, box.Start.Z).Round(roundDecimals);
            var c2       = new Vector3(box.End.X, box.Start.Y, box.Start.Z).Round(roundDecimals);
            var c3       = new Vector3(box.Center.X, box.End.Y, box.Start.Z).Round(roundDecimals);
            var centroid = new Vector3((c1.X + c2.X + c3.X) / 3, (c1.Y + c2.Y + c3.Y) / 3, box.End.Z);
            var c4       = (useCentroid ? centroid : new Vector3(box.Center.X, box.Center.Y, box.End.Z)).Round(roundDecimals);

            var faces = new[] {
                new[] { c1, c2, c3 },
                new[] { c4, c1, c3 },
                new[] { c4, c3, c2 },
                new[] { c4, c2, c1 }
            };

            var solid = new Solid(generator.Next("MapObject"));

            solid.Data.Add(new ObjectColor(Colour.GetRandomBrushColour()));

            foreach (var arr in faces)
            {
                var face = new Face(generator.Next("Face"))
                {
                    Plane   = new Plane(arr[0], arr[1], arr[2]),
                    Texture = { Name = texture }
                };
                face.Vertices.AddRange(arr);
                solid.Data.Add(face);
            }
            solid.DescendantsChanged();
            yield return(solid);
        }
Пример #2
0
        public IEnumerable <MapObject> Create(IDGenerator generator, Box box, ITexture texture, int roundDecimals)
        {
            var useCentroid = _useCentroid.GetValue();

            // The lower Z plane will be the triangle, with the lower Y value getting the two corners
            var c1       = new Coordinate(box.Start.X, box.Start.Y, box.Start.Z).Round(roundDecimals);
            var c2       = new Coordinate(box.End.X, box.Start.Y, box.Start.Z).Round(roundDecimals);
            var c3       = new Coordinate(box.Center.X, box.End.Y, box.Start.Z).Round(roundDecimals);
            var centroid = new Coordinate((c1.X + c2.X + c3.X) / 3, (c1.Y + c2.Y + c3.Y) / 3, box.End.Z);
            var c4       = (useCentroid ? centroid : new Coordinate(box.Center.X, box.Center.Y, box.End.Z)).Round(roundDecimals);

            var faces = new[] {
                new[] { c1, c2, c3 },
                new[] { c4, c1, c3 },
                new[] { c4, c3, c2 },
                new[] { c4, c2, c1 }
            };

            var solid = new Solid(generator.GetNextObjectID())
            {
                Colour = Colour.GetRandomBrushColour()
            };

            foreach (var arr in faces)
            {
                var face = new Face(generator.GetNextFaceID())
                {
                    Parent  = solid,
                    Plane   = new Plane(arr[0], arr[1], arr[2]),
                    Colour  = solid.Colour,
                    Texture = { Texture = texture }
                };
                face.Vertices.AddRange(arr.Select(x => new Vertex(x, face)));
                face.UpdateBoundingBox();
                face.AlignTextureToFace();
                solid.Faces.Add(face);
            }
            solid.UpdateBoundingBox();
            yield return(solid);
        }
Пример #3
0
        public ArchBrush()
        {
            _numSides = new NumericControl(this)
            {
                LabelText = "Number of sides"
            };
            _wallWidth = new NumericControl(this)
            {
                LabelText = "Wall width", Minimum = 1, Maximum = 1024, Value = 32, Precision = 1
            };
            _arc = new NumericControl(this)
            {
                LabelText = "Arc", Minimum = 1, Maximum = 360 * 4, Value = 360
            };
            _startAngle = new NumericControl(this)
            {
                LabelText = "Start angle", Minimum = 0, Maximum = 359, Value = 0
            };
            _addHeight = new NumericControl(this)
            {
                LabelText = "Add height", Minimum = -1024, Maximum = 1024, Value = 0, Precision = 1
            };
            _curvedRamp = new BooleanControl(this)
            {
                LabelText = "Curved ramp", Checked = false
            };
            _tiltAngle = new NumericControl(this)
            {
                LabelText = "Tilt angle", Minimum = -Atan2, Maximum = Atan2, Value = 0, Enabled = false, Precision = 1
            };
            _tiltInterp = new BooleanControl(this)
            {
                LabelText = "Tilt interpolation", Checked = false, Enabled = false
            };

            _curvedRamp.ValuesChanged += (s, b) => _tiltAngle.Enabled = _tiltInterp.Enabled = _curvedRamp.GetValue();
        }
Пример #4
0
        public IEnumerable <MapObject> Create(IDGenerator generator, Box box, ITexture texture, int roundDecimals)
        {
            var numSides = (int)_numSides.GetValue();

            if (numSides < 3)
            {
                yield break;
            }
            var wallWidth = _wallWidth.GetValue();

            if (wallWidth < 1)
            {
                yield break;
            }
            var arc = _arc.GetValue();

            if (arc < 1)
            {
                yield break;
            }
            var startAngle = _startAngle.GetValue();

            if (startAngle < 0 || startAngle > 359)
            {
                yield break;
            }
            var addHeight  = _addHeight.GetValue();
            var curvedRamp = _curvedRamp.GetValue();
            var tiltAngle  = curvedRamp ? _tiltAngle.GetValue() : 0;

            if (DMath.Abs(tiltAngle % 180) == 90)
            {
                yield break;
            }
            var tiltInterp = curvedRamp && _tiltInterp.GetValue();

            // Very similar to the pipe brush, except with options for start angle, arc, height and tilt
            var width  = box.Width;
            var length = box.Length;
            var height = box.Height;

            var majorOut = width / 2;
            var majorIn  = majorOut - wallWidth;
            var minorOut = length / 2;
            var minorIn  = minorOut - wallWidth;

            var start = DMath.DegreesToRadians(startAngle);
            var tilt  = DMath.DegreesToRadians(tiltAngle);
            var angle = DMath.DegreesToRadians(arc) / numSides;

            // Calculate the coordinates of the inner and outer ellipses' points
            var outer = new Coordinate[numSides + 1];
            var inner = new Coordinate[numSides + 1];

            for (var i = 0; i < numSides + 1; i++)
            {
                var a          = start + i * angle;
                var h          = i * addHeight;
                var interp     = tiltInterp ? DMath.Cos(DMath.PI / numSides * (i - numSides / 2M)) : 1;
                var tiltHeight = wallWidth / 2 * interp * DMath.Tan(tilt);

                var xval = box.Center.X + majorOut * DMath.Cos(a);
                var yval = box.Center.Y + minorOut * DMath.Sin(a);
                var zval = box.Start.Z + (curvedRamp ? h + tiltHeight : 0);
                outer[i] = new Coordinate(xval, yval, zval).Round(roundDecimals);

                xval     = box.Center.X + majorIn * DMath.Cos(a);
                yval     = box.Center.Y + minorIn * DMath.Sin(a);
                zval     = box.Start.Z + (curvedRamp ? h - tiltHeight : 0);
                inner[i] = new Coordinate(xval, yval, zval).Round(roundDecimals);
            }

            // Create the solids
            var colour = Colour.GetRandomBrushColour();
            var z      = new Coordinate(0, 0, height).Round(roundDecimals);

            for (var i = 0; i < numSides; i++)
            {
                var faces = new List <Coordinate[]>();

                // Since we are triangulating/splitting each arch segment, we need to generate 2 brushes per side
                if (curvedRamp)
                {
                    // The splitting orientation depends on the curving direction of the arch
                    if (addHeight >= 0)
                    {
                        faces.Add(new[] { outer[i], outer[i] + z, outer[i + 1] + z, outer[i + 1] });
                        faces.Add(new[] { outer[i + 1], outer[i + 1] + z, inner[i] + z, inner[i] });
                        faces.Add(new[] { inner[i], inner[i] + z, outer[i] + z, outer[i] });
                        faces.Add(new[] { outer[i] + z, inner[i] + z, outer[i + 1] + z });
                        faces.Add(new[] { outer[i + 1], inner[i], outer[i] });
                    }
                    else
                    {
                        faces.Add(new[] { inner[i + 1], inner[i + 1] + z, inner[i] + z, inner[i] });
                        faces.Add(new[] { outer[i], outer[i] + z, inner[i + 1] + z, inner[i + 1] });
                        faces.Add(new[] { inner[i], inner[i] + z, outer[i] + z, outer[i] });
                        faces.Add(new[] { inner[i + 1] + z, outer[i] + z, inner[i] + z });
                        faces.Add(new[] { inner[i], outer[i], inner[i + 1] });
                    }
                    yield return(MakeSolid(generator, faces, texture, colour));

                    faces.Clear();

                    if (addHeight >= 0)
                    {
                        faces.Add(new[] { inner[i + 1], inner[i + 1] + z, inner[i] + z, inner[i] });
                        faces.Add(new[] { inner[i], inner[i] + z, outer[i + 1] + z, outer[i + 1] });
                        faces.Add(new[] { outer[i + 1], outer[i + 1] + z, inner[i + 1] + z, inner[i + 1] });
                        faces.Add(new[] { inner[i + 1] + z, outer[i + 1] + z, inner[i] + z });
                        faces.Add(new[] { inner[i], outer[i + 1], inner[i + 1] });
                    }
                    else
                    {
                        faces.Add(new[] { outer[i], outer[i] + z, outer[i + 1] + z, outer[i + 1] });
                        faces.Add(new[] { inner[i + 1], inner[i + 1] + z, outer[i] + z, outer[i] });
                        faces.Add(new[] { outer[i + 1], outer[i + 1] + z, inner[i + 1] + z, inner[i + 1] });
                        faces.Add(new[] { outer[i] + z, inner[i + 1] + z, outer[i + 1] + z });
                        faces.Add(new[] { outer[i + 1], inner[i + 1], outer[i] });
                    }
                    yield return(MakeSolid(generator, faces, texture, colour));
                }
                else
                {
                    var h = i * addHeight * Coordinate.UnitZ;
                    faces.Add(new[] { outer[i], outer[i] + z, outer[i + 1] + z, outer[i + 1] }.Select(x => x + h).ToArray());
                    faces.Add(new[] { inner[i + 1], inner[i + 1] + z, inner[i] + z, inner[i] }.Select(x => x + h).ToArray());
                    faces.Add(new[] { outer[i + 1], outer[i + 1] + z, inner[i + 1] + z, inner[i + 1] }.Select(x => x + h).ToArray());
                    faces.Add(new[] { inner[i], inner[i] + z, outer[i] + z, outer[i] }.Select(x => x + h).ToArray());
                    faces.Add(new[] { inner[i + 1] + z, outer[i + 1] + z, outer[i] + z, inner[i] + z }.Select(x => x + h).ToArray());
                    faces.Add(new[] { inner[i], outer[i], outer[i + 1], inner[i + 1] }.Select(x => x + h).ToArray());
                    yield return(MakeSolid(generator, faces, texture, colour));
                }
            }
        }
Пример #5
0
 public TorusBrush()
 {
     _crossSides = new NumericControl(this)
     {
         LabelText = "Cross sec. sides"
     };
     _crossRadius = new NumericControl(this)
     {
         LabelText = "Ring width", Minimum = 16, Maximum = 1024, Value = 32, Precision = 1
     };
     _crossStartAngle = new NumericControl(this)
     {
         LabelText = "Cross sec. start", Minimum = 0, Maximum = 359, Value = 0
     };
     _crossMakeHollow = new BooleanControl(this)
     {
         LabelText = "Make hollow", Checked = false
     };
     _crossArc = new NumericControl(this)
     {
         LabelText = "Cross sec. arc", Minimum = 1, Maximum = 360, Value = 360, Enabled = false
     };
     _crossWallWidth = new NumericControl(this)
     {
         LabelText = "Hollow wall width", Minimum = 1, Maximum = 1024, Value = 16, Precision = 1, Enabled = false
     };
     _ringSides = new NumericControl(this)
     {
         LabelText = "Ring sides"
     };
     _ringArc = new NumericControl(this)
     {
         LabelText = "Ring arc", Minimum = 1, Maximum = 1080, Value = 360
     };
     _ringStartAngle = new NumericControl(this)
     {
         LabelText = "Ring start", Minimum = 0, Maximum = 359, Value = 0
     };
     _rotationHeight = new NumericControl(this)
     {
         LabelText = "Rotation height", Minimum = -1024, Maximum = 1024, Value = 0, Precision = 1
     };
     _crossMakeHollow.ValuesChanged += (s, b) => _crossWallWidth.Enabled = _crossArc.Enabled = _crossMakeHollow.GetValue();
 }
Пример #6
0
        public IEnumerable <MapObject> Create(IDGenerator generator, Box box, ITexture texture, int roundDecimals)
        {
            var crossSides = (int)_crossSides.GetValue();

            if (crossSides < 3)
            {
                yield break;
            }
            var crossWidth = _crossRadius.GetValue() * 2;

            if (crossWidth < 1)
            {
                yield break;
            }
            var crossMakeHollow = _crossMakeHollow.GetValue();
            var crossArc        = !crossMakeHollow ? 360 : (int)_crossArc.GetValue();

            if (crossArc < 1)
            {
                yield break;
            }
            var crossStartAngle = (int)_crossStartAngle.GetValue();

            if (crossStartAngle < 0 || crossStartAngle > 359)
            {
                yield break;
            }
            var crossWallWidth = _crossWallWidth.GetValue();

            if (crossWallWidth < 1)
            {
                yield break;
            }
            var ringSides = (int)_ringSides.GetValue();

            if (ringSides < 3)
            {
                yield break;
            }
            var ringArc = (int)_ringArc.GetValue();

            if (ringArc < 1)
            {
                yield break;
            }
            var ringStartAngle = (int)_ringStartAngle.GetValue();

            if (ringStartAngle < 0 || ringStartAngle > 359)
            {
                yield break;
            }
            var rotationHeight = _rotationHeight.GetValue();

            // Sort of a combination of cylinder and pipe brushes
            var width               = box.Width;
            var length              = box.Length;
            var height              = box.Height;
            var majorPrimary        = (width - crossWidth) / 2;          // Primary = donut circle
            var minorPrimary        = (length - crossWidth) / 2;
            var majorSecondaryOuter = crossWidth / 2;                    // Secondary = cross section circle
            var minorSecondaryOuter = height / 2;                        // Outer = Outer ring
            var majorSecondaryInner = (crossWidth - crossWallWidth) / 2; // Inner = inner ring (hollow only)
            var minorSecondaryInner = (height - crossWallWidth) / 2;

            var ringStart  = DMath.DegreesToRadians(ringStartAngle);
            var ringAngle  = DMath.DegreesToRadians(ringArc) / ringSides;
            var crossStart = DMath.DegreesToRadians(crossStartAngle);
            var crossAngle = DMath.DegreesToRadians(crossArc) / crossSides;
            var heightAdd  = rotationHeight / ringSides;

            // Rotate around the ring, generating each cross section
            var ringOuterSections = new List <Coordinate[]>();
            var ringInnerSections = new List <Coordinate[]>();

            for (var i = 0; i < ringSides + 1; i++)
            {
                var ring          = ringStart + i * ringAngle;
                var rxval         = box.Center.X + majorPrimary * DMath.Cos(ring);
                var ryval         = box.Center.Y + minorPrimary * DMath.Sin(ring);
                var rzval         = box.Center.Z;
                var crossSecOuter = new Coordinate[crossSides + 1];
                var crossSecInner = new Coordinate[crossSides + 1];
                for (var j = 0; j < crossSides + 1; j++)
                {
                    var cross = crossStart + j * crossAngle;
                    var xval  = majorSecondaryOuter * DMath.Cos(cross) * DMath.Cos(ring);
                    var yval  = majorSecondaryOuter * DMath.Cos(cross) * DMath.Sin(ring);
                    var zval  = minorSecondaryOuter * DMath.Sin(cross);
                    crossSecOuter[j] = new Coordinate(xval + rxval, yval + ryval, zval + rzval).Round(roundDecimals);
                    if (!crossMakeHollow)
                    {
                        continue;
                    }
                    xval             = majorSecondaryInner * DMath.Cos(cross) * DMath.Cos(ring);
                    yval             = majorSecondaryInner * DMath.Cos(cross) * DMath.Sin(ring);
                    zval             = minorSecondaryInner * DMath.Sin(cross);
                    crossSecInner[j] = new Coordinate(xval + rxval, yval + ryval, zval + rzval).Round(roundDecimals);
                }
                ringOuterSections.Add(crossSecOuter);
                ringInnerSections.Add(crossSecInner);
            }

            // Create the solids
            var colour = Colour.GetRandomBrushColour();

            for (var i = 0; i < ringSides; i++)
            {
                var vertical = Coordinate.UnitZ * heightAdd * i;
                var nexti    = i + 1;
                if (crossMakeHollow)
                {
                    // Use pipe cross sections
                    var outerPoints     = ringOuterSections[i];
                    var nextOuterPoints = ringOuterSections[nexti];
                    var innerPoints     = ringInnerSections[i];
                    var nextInnerPoints = ringInnerSections[nexti];
                    for (var j = 0; j < crossSides; j++)
                    {
                        var nextj = j + 1;
                        var faces = new List <Coordinate[]>();
                        faces.Add(new[] { outerPoints[j], outerPoints[nextj], nextOuterPoints[nextj], nextOuterPoints[j] }.Select(x => x + vertical).ToArray());
                        faces.Add(new[] { nextInnerPoints[j], nextInnerPoints[nextj], innerPoints[nextj], innerPoints[j] }.Select(x => x + vertical).ToArray());
                        faces.Add(new[] { innerPoints[nextj], nextInnerPoints[nextj], nextOuterPoints[nextj], outerPoints[nextj] }.Select(x => x + vertical).ToArray());
                        faces.Add(new[] { outerPoints[j], nextOuterPoints[j], nextInnerPoints[j], innerPoints[j] }.Select(x => x + vertical).ToArray());
                        faces.Add(new[] { innerPoints[j], innerPoints[nextj], outerPoints[nextj], outerPoints[j] }.Select(x => x + vertical).ToArray());
                        faces.Add(new[] { nextOuterPoints[j], nextOuterPoints[nextj], nextInnerPoints[nextj], nextInnerPoints[j] }.Select(x => x + vertical).ToArray());
                        yield return(MakeSolid(generator, faces, texture, colour));
                    }
                }
                else
                {
                    // Use cylindrical cross sections
                    var faces      = new List <Coordinate[]>();
                    var points     = ringOuterSections[i];
                    var nextPoints = ringOuterSections[nexti];
                    // Add the outer faces
                    for (var j = 0; j < crossSides; j++)
                    {
                        var nextj = (j + 1) % crossSides;
                        faces.Add(new[] { points[j], points[nextj], nextPoints[nextj], nextPoints[j] }.Select(x => x + vertical).ToArray());
                    }
                    // Add the cross section faces
                    faces.Add(points.Reverse().Select(x => x + vertical).ToArray());
                    faces.Add(nextPoints.Select(x => x + vertical).ToArray());
                    yield return(MakeSolid(generator, faces, texture, colour));
                }
            }
        }
Пример #7
0
        public Task OnInitialise()
        {
            _crossSides = new NumericControl(this)
            {
                LabelText = CrossSectionSides
            };
            _crossRadius = new NumericControl(this)
            {
                LabelText = RingWidth, Minimum = 16, Maximum = 1024, Value = 32, Precision = 1
            };
            _crossStartAngle = new NumericControl(this)
            {
                LabelText = CrossSectionStart, Minimum = 0, Maximum = 359, Value = 0
            };
            _crossMakeHollow = new BooleanControl(this)
            {
                LabelText = MakeHollow, Checked = false
            };
            _crossArc = new NumericControl(this)
            {
                LabelText = CrossSectionArc, Minimum = 1, Maximum = 360, Value = 360, Enabled = false
            };
            _crossWallWidth = new NumericControl(this)
            {
                LabelText = HollowWallWidth, Minimum = 1, Maximum = 1024, Value = 16, Precision = 1, Enabled = false
            };
            _ringSides = new NumericControl(this)
            {
                LabelText = RingSides
            };
            _ringArc = new NumericControl(this)
            {
                LabelText = RingArc, Minimum = 1, Maximum = 1080, Value = 360
            };
            _ringStartAngle = new NumericControl(this)
            {
                LabelText = RingStart, Minimum = 0, Maximum = 359, Value = 0
            };
            _rotationHeight = new NumericControl(this)
            {
                LabelText = RotationHeight, Minimum = -1024, Maximum = 1024, Value = 0, Precision = 1
            };
            _crossMakeHollow.ValuesChanged += (s, b) => _crossWallWidth.Enabled = _crossArc.Enabled = _crossMakeHollow.GetValue();

            return(Task.CompletedTask);
        }
Пример #8
0
        public async Task OnInitialise()
        {
            _numSides = new NumericControl(this)
            {
                LabelText = NumberOfSides
            };
            _wallWidth = new NumericControl(this)
            {
                LabelText = WallWidth, Minimum = 1, Maximum = 1024, Value = 32, Precision = 1
            };
            _arc = new NumericControl(this)
            {
                LabelText = Arc, Minimum = 1, Maximum = 360 * 4, Value = 360
            };
            _startAngle = new NumericControl(this)
            {
                LabelText = StartAngle, Minimum = 0, Maximum = 359, Value = 0
            };
            _addHeight = new NumericControl(this)
            {
                LabelText = AddHeight, Minimum = -1024, Maximum = 1024, Value = 0, Precision = 1
            };
            _curvedRamp = new BooleanControl(this)
            {
                LabelText = CurvedRamp, Checked = false
            };
            _tiltAngle = new NumericControl(this)
            {
                LabelText = TiltAngle, Minimum = -Atan2, Maximum = Atan2, Value = 0, Enabled = false, Precision = 1
            };
            _tiltInterp = new BooleanControl(this)
            {
                LabelText = TiltInterpolation, Checked = false, Enabled = false
            };

            _curvedRamp.ValuesChanged += (s, b) => _tiltAngle.Enabled = _tiltInterp.Enabled = _curvedRamp.GetValue();
        }