public static WPos LerpQuadratic(WPos a, WPos b, WAngle pitch, int mul, int div) { // Start with a linear lerp between the points var ret = Lerp(a, b, mul, div); if (pitch.Angle == 0) return ret; // Add an additional quadratic variation to height // Uses fp to avoid integer overflow var offset = (int)((float)((float)(b - a).Length*pitch.Tan()*mul*(div - mul)) / (float)(1024*div*div)); return new WPos(ret.X, ret.Y, ret.Z + offset); }
public static WPos LerpQuadratic(WPos a, WPos b, WAngle pitch, int mul, int div) { // Start with a linear lerp between the points var ret = Lerp(a, b, mul, div); if (pitch.Angle == 0) return ret; // Add an additional quadratic variation to height // Attempts to avoid integer overflow by keeping the intermediate variables reasonably sized var offset = (int)(((((((long)(b - a).Length * mul) / div) * (div - mul)) / div) * pitch.Tan()) / 1024); return new WPos(ret.X, ret.Y, ret.Z + offset); }
public static WRot FromYaw(WAngle yaw) { return new WRot(WAngle.Zero, WAngle.Zero, yaw); }
public WRot(WAngle roll, WAngle pitch, WAngle yaw) { Roll = roll; Pitch = pitch; Yaw = yaw; }
public WRot WithYaw(WAngle yaw) { return new WRot(Roll, Pitch, yaw); }
public int[] AsQuarternion() { // Angles increase clockwise var r = new WAngle(-Roll.Angle / 2); var p = new WAngle(-Pitch.Angle / 2); var y = new WAngle(-Yaw.Angle / 2); var cr = (long)r.Cos(); var sr = (long)r.Sin(); var cp = (long)p.Cos(); var sp = (long)p.Sin(); var cy = (long)y.Cos(); var sy = (long)y.Sin(); // Normalized to 1024 == 1.0 return new int[4] { (int)((sr*cp*cy - cr*sp*sy) / 1048576), // x (int)((cr*sp*cy + sr*cp*sy) / 1048576), // y (int)((cr*cp*sy - sr*sp*cy) / 1048576), // z (int)((cr*cp*cy + sr*sp*sy) / 1048576) // w }; }
public WRot WithYaw(WAngle yaw) { return(new WRot(Roll, Pitch, yaw)); }
public static WRot FromYaw(WAngle yaw) { return(new WRot(WAngle.Zero, WAngle.Zero, yaw)); }
public static WRot FromFacing(int facing) { return(new WRot(WAngle.Zero, WAngle.Zero, WAngle.FromFacing(facing))); }
public MapGrid(MiniYaml yaml) { FieldLoader.Load(this, yaml); // The default subcell index defaults to the middle entry var defaultSubCellIndex = (byte)DefaultSubCell; if (defaultSubCellIndex == byte.MaxValue) { DefaultSubCell = (SubCell)(SubCellOffsets.Length / 2); } else { var minSubCellOffset = SubCellOffsets.Length > 1 ? 1 : 0; if (defaultSubCellIndex < minSubCellOffset || defaultSubCellIndex >= SubCellOffsets.Length) { throw new InvalidDataException("Subcell default index must be a valid index into the offset triples and must be greater than 0 for mods with subcells"); } } // Rotation axes and amounts for the different slope types var southEast = new WVec(724, 724, 0); var southWest = new WVec(-724, 724, 0); var south = new WVec(0, 1024, 0); var east = new WVec(1024, 0, 0); var forward = new WAngle(64); var backward = -forward; var halfForward = new WAngle(48); var halfBackward = -halfForward; // Slope types are hardcoded following the convention from the TS and RA2 map format Ramps = new[] { // Flat new CellRamp(Type, WRot.None), // Two adjacent corners raised by half a cell new CellRamp(Type, new WRot(southEast, backward), tr: RampCornerHeight.Half, br: RampCornerHeight.Half), new CellRamp(Type, new WRot(southWest, backward), br: RampCornerHeight.Half, bl: RampCornerHeight.Half), new CellRamp(Type, new WRot(southEast, forward), tl: RampCornerHeight.Half, bl: RampCornerHeight.Half), new CellRamp(Type, new WRot(southWest, forward), tl: RampCornerHeight.Half, tr: RampCornerHeight.Half), // One corner raised by half a cell new CellRamp(Type, new WRot(south, halfBackward), br: RampCornerHeight.Half, split: RampSplit.X), new CellRamp(Type, new WRot(east, halfForward), bl: RampCornerHeight.Half, split: RampSplit.Y), new CellRamp(Type, new WRot(south, halfForward), tl: RampCornerHeight.Half, split: RampSplit.X), new CellRamp(Type, new WRot(east, halfBackward), tr: RampCornerHeight.Half, split: RampSplit.Y), // Three corners raised by half a cell new CellRamp(Type, new WRot(south, halfBackward), tr: RampCornerHeight.Half, br: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.X), new CellRamp(Type, new WRot(east, halfForward), tl: RampCornerHeight.Half, br: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.Y), new CellRamp(Type, new WRot(south, halfForward), tl: RampCornerHeight.Half, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.X), new CellRamp(Type, new WRot(east, halfBackward), tl: RampCornerHeight.Half, tr: RampCornerHeight.Half, br: RampCornerHeight.Half, split: RampSplit.Y), // Full tile sloped (mid corners raised by half cell, far corner by full cell) new CellRamp(Type, new WRot(south, backward), tr: RampCornerHeight.Half, br: RampCornerHeight.Full, bl: RampCornerHeight.Half), new CellRamp(Type, new WRot(east, forward), tl: RampCornerHeight.Half, br: RampCornerHeight.Half, bl: RampCornerHeight.Full), new CellRamp(Type, new WRot(south, forward), tl: RampCornerHeight.Full, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half), new CellRamp(Type, new WRot(east, backward), tl: RampCornerHeight.Half, tr: RampCornerHeight.Full, br: RampCornerHeight.Half), // Two opposite corners raised by half a cell new CellRamp(Type, WRot.None, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.Y), new CellRamp(Type, WRot.None, tl: RampCornerHeight.Half, br: RampCornerHeight.Half, split: RampSplit.Y), new CellRamp(Type, WRot.None, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.X), new CellRamp(Type, WRot.None, tl: RampCornerHeight.Half, br: RampCornerHeight.Half, split: RampSplit.X), }; TilesByDistance = CreateTilesByDistance(); }
public WRot WithPitch(WAngle pitch) { return(new WRot(Roll, pitch, Yaw)); }
public WRot WithRoll(WAngle roll) { return(new WRot(roll, Pitch, Yaw)); }