/// <summary> /// Creates a MapData instance /// </summary> /// <param name="index">The index value of the converted ValueMap</param> /// <param name="threshold">Minimum threshold to convert from</param> public static MapData CreateInstance(ValueMap map, int index, float threshold) { MapData output = CreateInstance <MapData>(); output.Initialize(map, index, threshold); return(output); }
public override object GetValue(NodePort port) { var graph = (Terra2DGraph)this.graph; if (graph.isComputing) { try { currentState = GetCurrentState(); if (currentState != previousState) { noise = NoiseGenerator.FractalNoise(graph.seed.GetHashCode(), graph.size, offset, noiseType, fractalType, depth, frequency); if (normalize) { noise = noise.MapToRange(0, 1); } previousState = currentState; } return(noise); } catch (System.Exception e) { graph.isComputing = false; throw e; } } return(null); }
public override object GetValue(NodePort port) { var graph = (Terra2DGraph)this.graph; if (graph.isComputing) { try { mask = GetInputValue <ValueMap>("mask", null); Vector2Int coord = new Vector2Int(); coord.x = (int)(graph.size.x * start.x); coord.y = (int)(graph.size.y * start.y); output = new SpaceColonizer(graph.seed, graph.size, stepSize, maxDistance, minDistance, leafCount, maxSteps, mask != null ? mask : null) .Generate(coord); } catch (System.Exception e) { graph.isComputing = false; throw e; } } return(output); }
/// <summary> /// Maps all values to a range /// </summary> public ValueMap MapToRange(float min, float max) { float cmin = float.MaxValue; float cmax = float.MinValue; ValueMap output = CreateInstance <ValueMap>(); output.Initialize(Width, Height); for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { if (values[x, y] < cmin) { cmin = values[x, y]; } else if (values[x, y] > cmax) { cmax = values[x, y]; } } } for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { output[x, y] = Mathf.Lerp(min, max, Mathf.InverseLerp(cmin, cmax, values[x, y])); } } return(output); }
public override object GetValue(NodePort port) { var graph = (Terra2DGraph)this.graph; if (graph.isComputing) { try { var input = GetInputValue("input", this.input); if (input == null) { input = CreateInstance <ValueMap>(); input.Initialize(graph.size); } output = new CaveGenerator(input, threshold, iterations, searchRadius, birthRule, deathRule).Generate(); return(output); } catch (System.Exception e) { graph.isComputing = false; throw e; } } return(null); }
/// <summary> /// Selects certain values from a map, and sets them to 1, and the rest to zero. Usefull for conversions /// </summary> public ValueMap Select(SelectOperation operation, float value) { ValueMap output = CreateInstance <ValueMap>(); output.Initialize(Width, Height); for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { switch (operation) { case SelectOperation.EqualTo: output[x, y] = values[x, y] == value ? 1 : 0; break; case SelectOperation.GreaterThan: output[x, y] = values[x, y] > value ? 1 : 0; break; case SelectOperation.LessThan: output[x, y] = values[x, y] < value ? 1 : 0; break; } } } return(output); }
public ValueMap Generate() { map = input.Clone(); for (int i = 0; i < iterations; i++) { buffer.Initialize(size); for (int x = 0; x < size.x; x++) { for (int y = 0; y < size.y; y++) { // Count alive neighbours int neighbours = map.GetNeighbours(new Vector2Int(x, y), searchRadius, true).FindAll(n => map[n] > threshold).Count; // cell is alive if (neighbours > birthRule) { buffer[x, y] = 1; } // cell is dead else if (neighbours < deathRule) { buffer[x, y] = 0; } } } map = buffer.Clone(); } return(map); }
/// <summary> /// Creates a ValueMap instance from a gradient /// </summary> public static ValueMap CreateInstance(int width, int height, Gradient gradient, bool vertical = false) { ValueMap output = CreateInstance <ValueMap>(); output.Initialize(width, height, gradient, vertical); return(output); }
/// <summary> /// Creates a ValueMap instance from a Texture2D (converted to grayscale) /// </summary> public static ValueMap CreateInstance(Texture2D image) { ValueMap output = CreateInstance <ValueMap>(); output.Initialize(image); return(output); }
/// <summary> /// Creates a ValueMap instance /// </summary> public static ValueMap CreateInstance(int width, int height) { ValueMap map = CreateInstance <ValueMap>(); map.Initialize(width, height); return(map); }
/// <summary> /// Creates a ValueMap instance /// </summary> public static ValueMap CreateInstance(Vector2Int size) { ValueMap map = CreateInstance <ValueMap>(); map.Initialize(size.x, size.y); return(map); }
/// <summary> /// /// </summary> /// <param name="seed">The seed for randomness</param> /// <param name="size">Width and Height of the maze</param> /// <param name="start">Starting point for the maze</param> /// <param name="wallSpacing">Spacing between passages</param> /// <param name="includeDiagonals">Allow diagonal passages</param> /// <param name="waviness">Higher values yield long passages with fewer dead ends, and vice versa</param> /// <param name="mask">Generate maze inside a mask, make sure the start point is inisde this mask</param> public MazeGenerator(string seed, Vector2Int size, Vector2Int start, int wallSpacing, bool includeDiagonals, float waviness = 0.5f, ValueMap mask = null) { this.seed = seed; this.size = size; this.start = start; this.wallSpacing = wallSpacing; this.includeDiagonals = includeDiagonals; this.waviness = waviness; this.mask = mask; }
public ValueMap GetValueMap(string id) { ValueMapOutputNode node = (ValueMapOutputNode)nodes.FindAll(n => n is ValueMapOutputNode).Find(n => ((ValueMapOutputNode)n).id == id); isComputing = true; ValueMap map = node.GetInputValue("valueMap", node.valueMap); isComputing = false; return(map); }
public SpaceColonizer(string seed, Vector2Int size, int stepSize, int maxDistance, int minDistance, int leafCount, int maxSteps, ValueMap mask = null) { this.seed = seed.GetHashCode(); this.size = size; this.stepSize = stepSize; this.maxDistance = maxDistance; this.minDistance = minDistance; this.leafCount = leafCount; this.maxSteps = maxSteps; this.mask = mask; }
/// <summary> /// Detects and returns edges in a map /// </summary> public ValueMap DetectEdges(float threshold) { ValueMap firstPass = CreateInstance <ValueMap>(); firstPass.Initialize(Width, Height); for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { firstPass[x, y] = 0; for (int i = x - 1; i <= x + 1; i++) { for (int j = y - 1; j <= y + 1; j++) { if (IsInsideBounds(i, j)) { if (Mathf.Abs(this[x, y] - this[i, j]) > threshold) { firstPass[x, y] = 1; break; } } } } } } ValueMap secondPass = CreateInstance <ValueMap>(); secondPass.Initialize(Width, Height); for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { if (firstPass.CountItemsInRegion(new Vector2Int(x - 1, y - 1), new Vector2Int(x + 1, y + 1), 1) > 8) { secondPass[x, y] = 0; } else { secondPass[x, y] = firstPass[x, y]; } } } return(secondPass); }
/// <summary> /// Create a new Cave Generator /// </summary> /// <param name="input">The input map, usually white noise</param> /// <param name="threshold">Input values below this threshold will be treated as zero</param> /// <param name="iterations">How many times to iterate the automata, higher values give smoother caves, but are slow</param> /// <param name="searchRadius">Neighbour search radius</param> /// <param name="birthRule"></param> /// <param name="deathRule"></param> public CaveGenerator(ValueMap input, float threshold, int iterations = 3, int searchRadius = 1, int birthRule = 2, int deathRule = 3) { this.threshold = threshold; this.iterations = iterations; this.searchRadius = searchRadius; this.birthRule = birthRule; this.deathRule = deathRule; this.input = input; size = new Vector2Int(input.Width, input.Height); map = ValueMap.CreateInstance(size); buffer = ValueMap.CreateInstance(size); }
/// <summary> /// Clamps values between a range /// </summary> public ValueMap Clamp(float min, float max) { ValueMap output = CreateInstance <ValueMap>(); output.Initialize(Width, Height); for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { output[x, y] = (this[x, y] < min) ? min : ((this[x, y] > max) ? max : this[x, y]); } } return(output); }
/// <summary> /// Applies am AnimationCurve on all values /// </summary> public ValueMap ApplyCurve(AnimationCurve curve) { ValueMap output = CreateInstance <ValueMap>(); output.Initialize(Width, Height); for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { output[x, y] = curve.Evaluate(this[x, y]); } } return(output); }
/// <summary> /// Create a clone of this map /// </summary> public ValueMap Clone() { ValueMap output = CreateInstance <ValueMap>(); output.Initialize(Width, Height); for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { output[x, y] = values[x, y]; } } return(output); }
public override object GetValue(NodePort port) { var graph = (Terra2DGraph)this.graph; if (graph.isComputing) { try { ValueMap a = GetInputValue("a", this.a); ValueMap b = GetInputValue("b", this.b); if (method == MathOperation.Add) { var output = a.Add(b); if (normalize) { output = output.MapToRange(0, 1); } return(output); } else if (method == MathOperation.Multiply) { var output = a.Multiply(b); if (normalize) { output = output.MapToRange(0, 1); } return(output); } else if (method == MathOperation.Subtract) { var output = a.Subtract(b); if (normalize) { output = output.MapToRange(0, 1); } return(output); } } catch (System.Exception e) { graph.isComputing = false; throw e; } } return(null); }
/// <summary> /// Subtracts two Value Maps /// </summary> public ValueMap Subtract(ValueMap map) { var output = Clone(); for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { if (map.IsInsideBounds(x, y)) { output.values[x, y] = values[x, y] - map.values[x, y]; } } } return(output); }
/// <summary> /// Multiplies two Value Maps /// </summary> public ValueMap Multiply(ValueMap map) { ValueMap output = Clone(); for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { if (map.IsInsideBounds(x, y)) { output.values[x, y] = values[x, y] * map.values[x, y]; } } } return(output); }
public override object GetValue(NodePort port) { var graph = (Terra2DGraph)this.graph; if (graph.isComputing) { try { noise = NoiseGenerator.WhiteNoise(graph.seed.GetHashCode(), graph.size, threshold); return(noise); } catch (System.Exception e) { graph.isComputing = false; throw e; } } return(null); }
/// <summary> /// Initialize map from a ValueMap /// </summary> /// <param name="index">The index value of the converted ValueMap</param> /// <param name="threshold">Minimum threshold to convert from</param> public void Initialize(ValueMap map, int index, float threshold) { Initialize(map.Width, map.Height); for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { if (map[x, y] > threshold) { this[x, y] = index; } else { this[x, y] = 0; } } } }
public override object GetValue(NodePort port) { var graph = (Terra2DGraph)this.graph; if (graph.isComputing) { try { output = ValueMap.CreateInstance(graph.size.x, graph.size.y, gradient, vertical); return(output); } catch (System.Exception e) { graph.isComputing = false; throw e; } } return(null); }
public ValueMap Generate() { // initialize maze = ValueMap.CreateInstance(size.x, size.y); random = new System.Random(seed.GetHashCode()); List <Vector2Int> activeCells = new List <Vector2Int>(); // add the start cell to the active list activeCells.Add(start); maze[start.x, start.y] = 1; // while active list is not empty while (activeCells.Count > 0) { // select cell from active list // randomly selected based on waviness // higher waviness produces long winding passages with fewer dead ends, and vice versa int cellIndex = random.NextDouble() > waviness?random.Next(activeCells.Count) : activeCells.Count - 1; var cell = activeCells[cellIndex]; // get untraversed neighbours of selected cell var neighbours = GetNeighbours(cell.x, cell.y); if (neighbours.Count > 0) { // randomly select a neighbour and connect it to the selected cell var neighbour = neighbours[random.Next(neighbours.Count)]; maze.ConnectCells(cell, neighbour, 1); // add that neighbour to the active list activeCells.Add(neighbour); } else { // if no traversable neighbours, remove cell from active list activeCells.Remove(cell); } } return(maze); }
public override object GetValue(NodePort port) { var graph = (Terra2DGraph)this.graph; if (graph.isComputing) { try { ValueMap input = GetInputValue("input", this.input); output = input.Dither(amount, threshold); return(output); } catch (System.Exception e) { graph.isComputing = false; throw e; } } return(null); }
public static ValueMap WhiteNoise(int seed, Vector2Int size, float threshold) { System.Random rand = new System.Random(seed); var noise = new FastNoise(seed); ValueMap output = ScriptableObject.CreateInstance <ValueMap>(); output.Initialize(size.x, size.y); for (int x = 0; x < size.x; x++) { for (int y = 0; y < size.y; y++) { output[x, y] = rand.NextDouble() > threshold?noise.GetWhiteNoise(x, y) : 0; } } return(output); }
/// <summary> /// Uses another ValueMap to mask this one, values less then or equal to zero are treated as masked /// </summary> public ValueMap ApplyMask(ValueMap mask, float threshold) { ValueMap output = Clone(); for (int x = 0; x < Width; x++) { for (int y = 0; y < Height; y++) { if (mask.IsInsideBounds(x, y)) { if (mask[x, y] <= threshold) { output[x, y] = 0; } } } } return(output); }
public static Texture2D ValueMapToTexture2D(ValueMap map) { map.MapToRange(0, 1); Texture2D texture = new Texture2D(map.Width, map.Height); Color[] colors = new Color[map.Width * map.Height]; for (int x = 0; x < map.Width; x++) { for (int y = 0; y < map.Height; y++) { colors[x + y * map.Width] = new Color(map[x, y], map[x, y], map[x, y]); } } texture.SetPixels(colors); texture.Apply(); return(texture); }