From 6d2ab937ce569735aefd3534b96f59963181074f Mon Sep 17 00:00:00 2001 From: UnknownShadow200 Date: Thu, 1 Sep 2016 20:11:03 +1000 Subject: [PATCH] Add a basic rotate transform. --- Drawing/Transform/RotateTransform.cs | 75 +++++++++++++++++++ Drawing/TransformFactories/RotateTransform.cs | 62 +++++++++++++++ .../TransformFactories/TransformFactory.cs | 1 + MCGalaxy_.csproj | 2 + 4 files changed, 140 insertions(+) create mode 100644 Drawing/Transform/RotateTransform.cs create mode 100644 Drawing/TransformFactories/RotateTransform.cs diff --git a/Drawing/Transform/RotateTransform.cs b/Drawing/Transform/RotateTransform.cs new file mode 100644 index 000000000..6d48a1fd1 --- /dev/null +++ b/Drawing/Transform/RotateTransform.cs @@ -0,0 +1,75 @@ +/* + Copyright 2015 MCGalaxy + + Dual-licensed under the Educational Community License, Version 2.0 and + the GNU General Public License, Version 3 (the "Licenses"); you may + not use this file except in compliance with the Licenses. You may + obtain a copy of the Licenses at + + http://www.opensource.org/licenses/ecl2.php + http://www.gnu.org/licenses/gpl-3.0.html + + Unless required by applicable law or agreed to in writing, + software distributed under the Licenses are distributed on an "AS IS" + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + or implied. See the Licenses for the specific language governing + permissions and limitations under the Licenses. + */ +using System; +using MCGalaxy.Drawing.Brushes; +using MCGalaxy.Drawing.Ops; + +namespace MCGalaxy.Drawing.Transforms { + + public sealed class RotateTransform : Transform { + + public override string Name { get { return "Rotate"; } } + public bool CentreOrigin; + double cosX, cosY, cosZ, sinX, sinY, sinZ; + int width, height, length; + Vec3S32 P; + + public void SetAngles(double xDeg, double yDeg, double zDeg) { + cosX = Math.Cos(xDeg * Math.PI / 180.0); + cosY = Math.Cos(yDeg * Math.PI / 180.0); + cosZ = Math.Cos(zDeg * Math.PI / 180.0); + + sinX = Math.Sin(xDeg * Math.PI / 180.0); + sinY = Math.Sin(yDeg * Math.PI / 180.0); + sinZ = Math.Sin(zDeg * Math.PI / 180.0); + } + + public override void Perform(Vec3S32[] marks, Player p, Level lvl, + DrawOp op, Brush brush, Action output) { + P = (op.Min + op.Max) / 2; + width = lvl.Width; height = lvl.Height; length = lvl.Length; + if (!CentreOrigin) P = op.Origin; + op.Perform(marks, p, lvl, brush, b => OutputBlock(b, output)); + } + + void OutputBlock(DrawOpBlock b, Action output) { + double dx = b.X - P.X, dy = b.Y - P.Y, dz = b.Z - P.Z; + double rotX = 0, rotY = 0, rotZ = 0; + + // Rotate X + rotY = cosX * dy - sinX * dz; + rotZ = sinX * dy + cosX * dz; + dy = rotY; dz = rotZ; + + // Rotate Y + rotX = cosY * dx + sinY * dz; + rotZ = -sinY * dx + cosY * dz; + dx = rotX; dz = rotZ; + + // Rotate Z + rotX = cosZ * dx - sinZ * dy; + rotY = sinZ * dx + cosZ * dy; + dx = rotX; dy = rotY; + + b.X = (ushort)(dx + P.X + ((dx % 1) >= 0.5 ? 1 : 0)); + b.Y = (ushort)(dy + P.Y + ((dy % 1) >= 0.5 ? 1 : 0)); + b.Z = (ushort)(dz + P.Z + ((dz % 1) >= 0.5 ? 1 : 0)); + output(b); + } + } +} diff --git a/Drawing/TransformFactories/RotateTransform.cs b/Drawing/TransformFactories/RotateTransform.cs new file mode 100644 index 000000000..5cc4a6e74 --- /dev/null +++ b/Drawing/TransformFactories/RotateTransform.cs @@ -0,0 +1,62 @@ +/* + Copyright 2015 MCGalaxy + + Dual-licensed under the Educational Community License, Version 2.0 and + the GNU General Public License, Version 3 (the "Licenses"); you may + not use this file except in compliance with the Licenses. You may + obtain a copy of the Licenses at + + http://www.opensource.org/licenses/ecl2.php + http://www.gnu.org/licenses/gpl-3.0.html + + Unless required by applicable law or agreed to in writing, + software distributed under the Licenses are distributed on an "AS IS" + BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express + or implied. See the Licenses for the specific language governing + permissions and limitations under the Licenses. + */ +using System; +using MCGalaxy.Commands.Building; + +namespace MCGalaxy.Drawing.Transforms { + + public sealed class RotateTransformFactory : TransformFactory { + public override string Name { get { return "Rotate"; } } + public override string[] Help { get { return HelpString; } } + + static string[] HelpString = new [] { + "%TArguments: [angleX] [angleY] [angleZ] ", + "%H[angle] values are values in degrees.", + "%H[centre] if given, indicates to scale from the centre of a draw operation, " + + "instead of outwards from the first mark. Recommended for cuboid and cylinder.", + }; + + public override Transform Construct(Player p, string message) { + string[] args = message.Split(' '); + if (args.Length < 3 || args.Length > 4) { Player.MessageLines(p, Help); return null; } + double angleX, angleY, angleZ; + RotateTransform rotater = new RotateTransform(); + + if (!ParseAngle(p, args[0], out angleX)) return null; + if (!ParseAngle(p, args[1], out angleY)) return null; + if (!ParseAngle(p, args[2], out angleZ)) return null; + rotater.SetAngles(angleX, angleY, angleZ); + + if (args.Length == 3) return rotater; // no centre argument + if (!args[args.Length - 1].CaselessEq("centre")) { + Player.Message(p, "The mode must be either \"centre\", or not given."); return null; + } + return rotater; + } + + static bool ParseAngle(Player p, string input, out double angle) { + if (!Double.TryParse(input, out angle)) { + Player.MessageLines(p, HelpString); return false; + } + if (angle < -360 || angle > 360) { + Player.Message(p, "Angle must be between -360 and 360."); return false; + } + return true; + } + } +} diff --git a/Drawing/TransformFactories/TransformFactory.cs b/Drawing/TransformFactories/TransformFactory.cs index f0c483408..ad39aa161 100644 --- a/Drawing/TransformFactories/TransformFactory.cs +++ b/Drawing/TransformFactories/TransformFactory.cs @@ -35,6 +35,7 @@ namespace MCGalaxy.Drawing.Transforms { public static List Transforms = new List() { new NoTransformFactory(), new ScaleTransformFactory(), + new RotateTransformFactory(), }; public static string Available { get { return Transforms.Join(b => b.Name); } } diff --git a/MCGalaxy_.csproj b/MCGalaxy_.csproj index aefe86053..ce6ba880b 100644 --- a/MCGalaxy_.csproj +++ b/MCGalaxy_.csproj @@ -455,8 +455,10 @@ + +