public Heightmap CloneAndFlipX() { Heightmap heightmap = Clone(); heightmap.heightmapData.FlipXInPlace(); return(heightmap); }
public ShadowReceiver(Heightmap heightmap, Oblique heightmapExtendDirection) { if (heightmap == null) { throw new ArgumentNullException("heightmap"); } this.heightmap = heightmap; this.heightmapExtendDirection = heightmapExtendDirection; }
/// <param name="baseHeightmap">NOTE: This gets used as a proxy for "is this a shadow receiver"</param> public void RefreshFromInstructions(Heightmap baseHeightmap) { if (instructions != null) // No instructions means we are raw data (do not touch!) { ClearToHeight(0); // <- Start blank. foreach (var instruction in instructions) { instruction.Process(this, baseHeightmap); } if (baseHeightmap == null) { Optimise(); } } }
/// <summary>Deserialize into new object instance</summary> public ShadowReceiver(AnimationDeserializeContext context) { heightmap = new Heightmap(context); heightmapExtendDirection = context.br.ReadOblique(); }
/// <summary>Create a new heightmap that extends its content (non-default heights) out in oblique directions (sutiable for creating shadow heightmaps)</summary> public Heightmap CreateExtendedOblique(Oblique oblique) { // Expand the region containing content in the specified oblique direction(s) #region ASCII Art... // // Given a heightmap that looks like this: // ________ // | /\ /\ | // |/ \/ \| // |\ /| // |/ \| // |\ /\ /| // |_\/__\/_| // // Expand it by projecting its content in the oblique direction: // ________________ // |. | /\ /\ | | // | . |/ \/ \| | // | .|\ /. | // | ./ \|. | // | |\ /\ /| . | // |___|_\/__\/_|__.| // #endregion int extendedLeft = StartX; int extendedRight = EndX - 1; // <- inclusive for (int z = StartZ; z < EndZ; z++) { for (int x = StartX; x < EndX; x++) { if (this[x, z] != DefaultHeight) // Has content to extend { int deltaFromFront = z - StartZ; // (positive) int deltaFromBack = z - (EndZ - 1); // (negative) int frontX = x - deltaFromFront * (int)oblique; int backX = x - deltaFromBack * (int)oblique; // Expand: if (frontX < extendedLeft) { extendedLeft = frontX; } if (frontX > extendedRight) { extendedRight = frontX; } if (backX < extendedLeft) { extendedLeft = backX; } if (backX > extendedRight) { extendedRight = backX; } } } } // HACK: To allow edges to have zero values when filled, without adding expansion to the Fill methods, // simply expand by one pixel here: // TODO: Allow the FillLeft/FillRight methods to automatically expand the size of the heightmap sideways if necessary // (So that zero values on the very edge aren't lost) extendedLeft -= 1; extendedRight += 1; Rectangle destinationBounds = new Rectangle(extendedLeft, StartZ, extendedRight - extendedLeft + 1, EndZ - StartZ); Heightmap destination = new Heightmap(DefaultHeight); destination.heightmapData = new Data2D <byte>(destinationBounds); // Copy while extending content for (int destinationZ = destination.StartZ; destinationZ < destination.EndZ; destinationZ++) { for (int destinationX = destination.StartX; destinationX < destination.EndX; destinationX++) { // We could add a bunch of early-outs here (but we don't care if this is a tad slow) int sourceX = destinationX, sourceZ = destinationZ; // Try and extend to find content: if (this[sourceX, sourceZ] == DefaultHeight) { // Search backwards to back of heightmap while (true) { sourceZ += 1; sourceX += (int)oblique; if (sourceZ >= this.EndZ) { goto searchForward; } if (this[sourceX, sourceZ] != DefaultHeight) { goto done; } } // Search forward to front of heightmap searchForward: sourceX = destinationX; sourceZ = destinationZ; while (true) { sourceZ -= 1; sourceX -= (int)oblique; if (sourceZ < this.StartZ) { goto fail; } if (this[sourceX, sourceZ] != DefaultHeight) { goto done; } } fail: sourceX = destinationX; sourceZ = destinationZ; done: ; } destination[destinationX, destinationZ] = this[sourceX, sourceZ]; } } return(destination); }
public HeightmapView(Heightmap heightmap, Position position, bool flipX) { this.heightmap = heightmap; this.position = position; this.flipX = flipX; }
/// <param name="heightmap">The heightmap to apply the instruction to</param> /// <param name="baseHeightmap">When creating ShadowReceiver heightmaps, the AnimationSet heightmap</param> public void Process(Heightmap heightmap, Heightmap baseHeightmap) { switch (Operation) { case HeightmapOp.ClearToHeight: heightmap.ClearToHeight(Height); break; case HeightmapOp.SetFromFlatBaseMask: heightmap.SetFromFlatBaseMask(Mask.data, Height); break; case HeightmapOp.SetFromFlatTopMask: heightmap.SetFromFlatTopMask(Mask.data, Height); break; case HeightmapOp.SetFromObliqueTopMask: heightmap.SetFromObliqueTopMask(Mask.data, FrontEdgeDepth, ObliqueDirection); break; case HeightmapOp.SetFromRailingMask: heightmap.SetFromRailingMask(Mask.data); break; case HeightmapOp.SetFromFrontEdge: heightmap.SetFromFrontEdge(Mask.data, FrontEdgeDepth, Depth, ObliqueDirection, Slope, Offset); break; case HeightmapOp.SetFlatRelative: heightmap.SetFlatRelative(Mask.data, Height, Offset); break; case HeightmapOp.SetFromSideOblique: heightmap.SetFromObliqueSide(Mask.data, ObliqueDirection, Offset); break; case HeightmapOp.CreateExtendedObliqueFromBase: { var temp = baseHeightmap.CreateExtendedOblique(ObliqueDirection); heightmap.heightmapData = temp.heightmapData; // <- suck out its brains heightmap.DefaultHeight = temp.DefaultHeight; } break; case HeightmapOp.ExtendOblique: { var temp = heightmap.CreateExtendedOblique(ObliqueDirection); heightmap.heightmapData = temp.heightmapData; // <- suck out its brains heightmap.DefaultHeight = temp.DefaultHeight; } break; case HeightmapOp.FillLeft: heightmap.FillLeft(null); break; case HeightmapOp.FillLeftFixedHeight: heightmap.FillLeft(Height); break; case HeightmapOp.FillRight: heightmap.FillRight(null); break; case HeightmapOp.FillRightFixedHeight: heightmap.FillRight(Height); break; } }
public ShadowReceiver(byte height) { heightmap = new Heightmap(height); // No data heightmap (single height) }