public IEnumerable <MapObject> Create(IDGenerator generator, Box box, ITexture texture, int roundDecimals) { var numSides = (int)_numSides.GetValue(); if (numSides < 3) { yield break; } // This is all very similar to the cylinder brush. var width = box.Width; var length = box.Length; var major = width / 2; var minor = length / 2; var angle = 2 * DMath.PI / numSides; var points = new Coordinate[numSides]; for (var i = 0; i < numSides; i++) { var a = i * angle; var xval = box.Center.X + major * DMath.Cos(a); var yval = box.Center.Y + minor * DMath.Sin(a); var zval = box.Start.Z; points[i] = new Coordinate(xval, yval, zval).Round(roundDecimals); } var faces = new List <Coordinate[]>(); var point = new Coordinate(box.Center.X, box.Center.Y, box.End.Z).Round(roundDecimals); for (var i = 0; i < numSides; i++) { var next = (i + 1) % numSides; faces.Add(new[] { points[i], point, points[next] }); } faces.Add(points.ToArray()); 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); }
public IEnumerable <MapObject> Create(IDGenerator generator, Box box, ITexture texture, int roundDecimals) { var wallWidth = _wallWidth.GetValue(); if (wallWidth < 1) { yield break; } var numSides = (int)_numSides.GetValue(); if (numSides < 3) { yield break; } // Very similar to the cylinder, except we have multiple solids this time 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 angle = 2 * DMath.PI / numSides; // Calculate the X and Y points for the inner and outer ellipses var outer = new Coordinate[numSides]; var inner = new Coordinate[numSides]; for (var i = 0; i < numSides; i++) { var a = i * angle; var xval = box.Center.X + majorOut * DMath.Cos(a); var yval = box.Center.Y + minorOut * DMath.Sin(a); var zval = box.Start.Z; 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); 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[]>(); var next = (i + 1) % numSides; faces.Add(new[] { outer[i], outer[i] + z, outer[next] + z, outer[next] }); faces.Add(new[] { inner[next], inner[next] + z, inner[i] + z, inner[i] }); faces.Add(new[] { outer[next], outer[next] + z, inner[next] + z, inner[next] }); faces.Add(new[] { inner[i], inner[i] + z, outer[i] + z, outer[i] }); faces.Add(new[] { inner[next] + z, outer[next] + z, outer[i] + z, inner[i] + z }); faces.Add(new[] { inner[i], outer[i], outer[next], inner[next] }); yield return(MakeSolid(generator, faces, texture, colour)); } }
public IEnumerable <IMapObject> Create(UniqueNumberGenerator generator, Box box, string texture, int roundDecimals) { var numSides = (int)_numSides.GetValue(); if (numSides < 3) { yield break; } // This is all very similar to the cylinder brush. var width = box.Width; var length = box.Length; var major = width / 2; var minor = length / 2; var angle = 2 * Math.PI / numSides; var points = new Vector3[numSides]; for (var i = 0; i < numSides; i++) { var a = i * angle; var xval = box.Center.X + major * (float)Math.Cos(a); var yval = box.Center.Y + minor * (float)Math.Sin(a); var zval = box.Start.Z; points[i] = new Vector3(xval, yval, zval).Round(roundDecimals); } var faces = new List <Vector3[]>(); var point = new Vector3(box.Center.X, box.Center.Y, box.End.Z).Round(roundDecimals); for (var i = 0; i < numSides; i++) { var next = (i + 1) % numSides; faces.Add(new[] { points[i], point, points[next] }); } faces.Add(points.ToArray()); 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); }
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)); } } }
public IEnumerable <MapObject> Create(IDGenerator generator, Box box, ITexture texture, int roundDecimals) { var numSides = (int)_numSides.GetValue(); if (numSides < 3) { yield break; } // Cylinders can be elliptical so use both major and minor rather than just the radius // NOTE: when a low number (< 10ish) of faces are selected this will cause the cylinder to not touch all the edges of the box. var width = box.Width; var length = box.Length; var height = box.Height; var major = width / 2; var minor = length / 2; var angle = 2 * DMath.PI / numSides; // Calculate the X and Y points for the ellipse var points = new Coordinate[numSides]; for (var i = 0; i < numSides; i++) { var a = i * angle; var xval = box.Center.X + major * DMath.Cos(a); var yval = box.Center.Y + minor * DMath.Sin(a); var zval = box.Start.Z; points[i] = new Coordinate(xval, yval, zval).Round(roundDecimals); } var faces = new List <Coordinate[]>(); // Add the vertical faces var z = new Coordinate(0, 0, height).Round(roundDecimals); for (var i = 0; i < numSides; i++) { var next = (i + 1) % numSides; faces.Add(new[] { points[i], points[i] + z, points[next] + z, points[next] }); } // Add the elliptical top and bottom faces faces.Add(points.ToArray()); faces.Add(points.Select(x => x + z).Reverse().ToArray()); // Nothing new here, move along 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); }
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)); } } }
public IEnumerable <MapObject> Create(IDGenerator generator, Box box, ITexture texture, int roundDecimals) { var numSides = (int)_numSides.GetValue(); if (numSides < 3) { yield break; } var width = box.Width; var length = box.Length; var height = box.Height; var major = width / 2; var minor = length / 2; var heightRadius = height / 2; var angleV = DMath.DegreesToRadians(180) / numSides; var angleH = DMath.DegreesToRadians(360) / numSides; var faces = new List <Coordinate[]>(); var bottom = new Coordinate(box.Center.X, box.Center.Y, box.Start.Z).Round(roundDecimals); var top = new Coordinate(box.Center.X, box.Center.Y, box.End.Z).Round(roundDecimals); for (var i = 0; i < numSides; i++) { // Top -> bottom var zAngleStart = angleV * i; var zAngleEnd = angleV * (i + 1); var zStart = heightRadius * DMath.Cos(zAngleStart); var zEnd = heightRadius * DMath.Cos(zAngleEnd); var zMultStart = DMath.Sin(zAngleStart); var zMultEnd = DMath.Sin(zAngleEnd); for (var j = 0; j < numSides; j++) { // Go around the circle in X/Y var xyAngleStart = angleH * j; var xyAngleEnd = angleH * ((j + 1) % numSides); var xyStartX = major * DMath.Cos(xyAngleStart); var xyStartY = minor * DMath.Sin(xyAngleStart); var xyEndX = major * DMath.Cos(xyAngleEnd); var xyEndY = minor * DMath.Sin(xyAngleEnd); var one = (new Coordinate(xyStartX * zMultStart, xyStartY * zMultStart, zStart) + box.Center).Round(roundDecimals); var two = (new Coordinate(xyEndX * zMultStart, xyEndY * zMultStart, zStart) + box.Center).Round(roundDecimals); var three = (new Coordinate(xyEndX * zMultEnd, xyEndY * zMultEnd, zEnd) + box.Center).Round(roundDecimals); var four = (new Coordinate(xyStartX * zMultEnd, xyStartY * zMultEnd, zEnd) + box.Center).Round(roundDecimals); if (i == 0) { // Top faces are triangles faces.Add(new[] { top, three, four }); } else if (i == numSides - 1) { // Bottom faces are also triangles faces.Add(new[] { bottom, one, two }); } else { // Inner faces are quads faces.Add(new[] { one, two, three, four }); } } } yield return(MakeSolid(generator, faces, texture, Colour.GetRandomBrushColour())); }
public IEnumerable <IMapObject> Create(UniqueNumberGenerator generator, Box box, string texture, int roundDecimals) { var numSides = (int)_numSides.GetValue(); if (numSides < 3) { yield break; } // Cylinders can be elliptical so use both major and minor rather than just the radius // NOTE: when a low number (< 10ish) of faces are selected this will cause the cylinder to not touch all the edges of the box. var width = box.Width; var length = box.Length; var height = box.Height; var major = width / 2; var minor = length / 2; var angle = 2 * (float)Math.PI / numSides; // Calculate the X and Y points for the ellipse var points = new Vector3[numSides]; for (var i = 0; i < numSides; i++) { var a = i * angle; var xval = box.Center.X + major * (float)Math.Cos(a); var yval = box.Center.Y + minor * (float)Math.Sin(a); var zval = box.Start.Z; points[i] = new Vector3(xval, yval, zval).Round(roundDecimals); } var faces = new List <Vector3[]>(); // Add the vertical faces var z = new Vector3(0, 0, height).Round(roundDecimals); for (var i = 0; i < numSides; i++) { var next = (i + 1) % numSides; faces.Add(new[] { points[i], points[i] + z, points[next] + z, points[next] }); } // Add the elliptical top and bottom faces faces.Add(points.ToArray()); faces.Add(points.Select(x => x + z).Reverse().ToArray()); // Nothing new here, move along 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); }