1016 lines
23 KiB
C#
1016 lines
23 KiB
C#
using System;
|
|
using UnityEngine;
|
|
|
|
namespace ErosionBrushPlugin
|
|
{
|
|
[Serializable]
|
|
public class Matrix
|
|
{
|
|
public class Stacker
|
|
{
|
|
public CoordRect smallRect;
|
|
|
|
public CoordRect bigRect;
|
|
|
|
public bool preserveDetail = true;
|
|
|
|
private Matrix downscaled;
|
|
|
|
private Matrix upscaled;
|
|
|
|
private Matrix difference;
|
|
|
|
private bool isDownscaled;
|
|
|
|
public Matrix matrix
|
|
{
|
|
get
|
|
{
|
|
if (isDownscaled)
|
|
{
|
|
return downscaled;
|
|
}
|
|
return upscaled;
|
|
}
|
|
}
|
|
|
|
public Stacker(CoordRect smallRect, CoordRect bigRect)
|
|
{
|
|
this.smallRect = smallRect;
|
|
this.bigRect = bigRect;
|
|
isDownscaled = false;
|
|
if (bigRect == smallRect)
|
|
{
|
|
upscaled = (downscaled = new Matrix(bigRect));
|
|
return;
|
|
}
|
|
downscaled = new Matrix(smallRect);
|
|
upscaled = new Matrix(bigRect);
|
|
difference = new Matrix(bigRect);
|
|
}
|
|
|
|
public void ToSmall()
|
|
{
|
|
if (!(bigRect == smallRect))
|
|
{
|
|
Matrix obj = upscaled;
|
|
CoordRect newRect = smallRect;
|
|
Matrix result = downscaled;
|
|
downscaled = obj.Resize(newRect, 1f, result);
|
|
if (preserveDetail)
|
|
{
|
|
Matrix obj2 = downscaled;
|
|
newRect = bigRect;
|
|
result = difference;
|
|
difference = obj2.Resize(newRect, 1f, result);
|
|
difference.Blur();
|
|
difference.InvSubtract(upscaled);
|
|
}
|
|
isDownscaled = true;
|
|
}
|
|
}
|
|
|
|
public void ToBig()
|
|
{
|
|
if (!(bigRect == smallRect))
|
|
{
|
|
Matrix obj = downscaled;
|
|
CoordRect newRect = bigRect;
|
|
Matrix result = upscaled;
|
|
upscaled = obj.Resize(newRect, 1f, result);
|
|
upscaled.Blur();
|
|
if (preserveDetail)
|
|
{
|
|
upscaled.Add(difference);
|
|
}
|
|
isDownscaled = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
public float[] array;
|
|
|
|
public CoordRect rect;
|
|
|
|
public int pos;
|
|
|
|
public float this[int x, int z]
|
|
{
|
|
get
|
|
{
|
|
return array[(z - rect.offset.z) * rect.size.x + x - rect.offset.x];
|
|
}
|
|
set
|
|
{
|
|
array[(z - rect.offset.z) * rect.size.x + x - rect.offset.x] = value;
|
|
}
|
|
}
|
|
|
|
public float this[Coord c]
|
|
{
|
|
get
|
|
{
|
|
return array[(c.z - rect.offset.z) * rect.size.x + c.x - rect.offset.x];
|
|
}
|
|
set
|
|
{
|
|
array[(c.z - rect.offset.z) * rect.size.x + c.x - rect.offset.x] = value;
|
|
}
|
|
}
|
|
|
|
public float this[Vector3 pos]
|
|
{
|
|
get
|
|
{
|
|
return array[((int)pos.z - rect.offset.z) * rect.size.x + (int)pos.x - rect.offset.x];
|
|
}
|
|
set
|
|
{
|
|
array[((int)pos.z - rect.offset.z) * rect.size.x + (int)pos.x - rect.offset.x] = value;
|
|
}
|
|
}
|
|
|
|
public float nextX
|
|
{
|
|
get
|
|
{
|
|
return array[pos + 1];
|
|
}
|
|
set
|
|
{
|
|
array[pos + 1] = value;
|
|
}
|
|
}
|
|
|
|
public float prevX
|
|
{
|
|
get
|
|
{
|
|
return array[pos - 1];
|
|
}
|
|
set
|
|
{
|
|
array[pos - 1] = value;
|
|
}
|
|
}
|
|
|
|
public float nextZ
|
|
{
|
|
get
|
|
{
|
|
return array[pos + rect.size.x];
|
|
}
|
|
set
|
|
{
|
|
array[pos + rect.size.x] = value;
|
|
}
|
|
}
|
|
|
|
public float prevZ
|
|
{
|
|
get
|
|
{
|
|
return array[pos - rect.size.x];
|
|
}
|
|
set
|
|
{
|
|
array[pos - rect.size.x] = value;
|
|
}
|
|
}
|
|
|
|
public float nextXnextZ
|
|
{
|
|
get
|
|
{
|
|
return array[pos + rect.size.x + 1];
|
|
}
|
|
set
|
|
{
|
|
array[pos + rect.size.x + 1] = value;
|
|
}
|
|
}
|
|
|
|
public float prevXnextZ
|
|
{
|
|
get
|
|
{
|
|
return array[pos + rect.size.x - 1];
|
|
}
|
|
set
|
|
{
|
|
array[pos + rect.size.x - 1] = value;
|
|
}
|
|
}
|
|
|
|
public float nextXprevZ
|
|
{
|
|
get
|
|
{
|
|
return array[pos - rect.size.x + 1];
|
|
}
|
|
set
|
|
{
|
|
array[pos - rect.size.x + 1] = value;
|
|
}
|
|
}
|
|
|
|
public float prevXprevZ
|
|
{
|
|
get
|
|
{
|
|
return array[pos - rect.size.x - 1];
|
|
}
|
|
set
|
|
{
|
|
array[pos - rect.size.x - 1] = value;
|
|
}
|
|
}
|
|
|
|
public Matrix(CoordRect rect)
|
|
{
|
|
this.rect = rect;
|
|
array = new float[rect.size.x * rect.size.z];
|
|
}
|
|
|
|
public Matrix(Coord offset, Coord size)
|
|
{
|
|
rect = new CoordRect(offset, size);
|
|
array = new float[rect.size.x * rect.size.z];
|
|
}
|
|
|
|
public void ChangeRect(CoordRect newRect)
|
|
{
|
|
rect.offset.x = newRect.offset.x;
|
|
rect.offset.z = newRect.offset.z;
|
|
if (rect.size.x != newRect.size.x || rect.size.z != newRect.size.z)
|
|
{
|
|
rect = newRect;
|
|
array = new float[rect.size.x * rect.size.z];
|
|
}
|
|
}
|
|
|
|
public Matrix Clone(Matrix result = null)
|
|
{
|
|
if (result == null)
|
|
{
|
|
result = new Matrix(rect);
|
|
}
|
|
result.rect = rect;
|
|
result.pos = pos;
|
|
if (result.array.Length != array.Length)
|
|
{
|
|
result.array = new float[array.Length];
|
|
}
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
result.array[i] = array[i];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public void SetPos(int x, int z)
|
|
{
|
|
pos = (z - rect.offset.z) * rect.size.x + x - rect.offset.x;
|
|
}
|
|
|
|
public void SetPos(int x, int z, int s)
|
|
{
|
|
pos = (z - rect.offset.z) * rect.size.x + x - rect.offset.x + s * rect.size.x * rect.size.z;
|
|
}
|
|
|
|
public void MoveX()
|
|
{
|
|
pos++;
|
|
}
|
|
|
|
public void MoveZ()
|
|
{
|
|
pos += rect.size.x;
|
|
}
|
|
|
|
public void MovePrevX()
|
|
{
|
|
pos--;
|
|
}
|
|
|
|
public void MovePrevZ()
|
|
{
|
|
pos -= rect.size.x;
|
|
}
|
|
|
|
public float[,] ReadHeighmap(TerrainData data, float height = 1f)
|
|
{
|
|
CoordRect centerRect = CoordRect.Intersect(rect, new CoordRect(0, 0, data.heightmapResolution, data.heightmapResolution));
|
|
float[,] heights = data.GetHeights(centerRect.offset.x, centerRect.offset.z, centerRect.size.x, centerRect.size.z);
|
|
Coord min = centerRect.Min;
|
|
Coord max = centerRect.Max;
|
|
for (int i = min.x; i < max.x; i++)
|
|
{
|
|
for (int j = min.z; j < max.z; j++)
|
|
{
|
|
this[i, j] = heights[j - min.z, i - min.x] * height;
|
|
}
|
|
}
|
|
RemoveBorders(centerRect);
|
|
return heights;
|
|
}
|
|
|
|
public void WriteHeightmap(TerrainData data, float[,] array = null, float brushFallof = 0.5f)
|
|
{
|
|
CoordRect coordRect = CoordRect.Intersect(rect, new CoordRect(0, 0, data.heightmapResolution, data.heightmapResolution));
|
|
if (array == null || array.Length != coordRect.size.x * coordRect.size.z)
|
|
{
|
|
array = new float[coordRect.size.z, coordRect.size.x];
|
|
}
|
|
Coord min = coordRect.Min;
|
|
Coord max = coordRect.Max;
|
|
for (int i = min.x; i < max.x; i++)
|
|
{
|
|
for (int j = min.z; j < max.z; j++)
|
|
{
|
|
float num = Fallof(i, j, brushFallof);
|
|
if (!Mathf.Approximately(num, 0f))
|
|
{
|
|
array[j - min.z, i - min.x] = this[i, j] * num + array[j - min.z, i - min.x] * (1f - num);
|
|
}
|
|
}
|
|
}
|
|
data.SetHeights(coordRect.offset.x, coordRect.offset.z, array);
|
|
}
|
|
|
|
public float[,,] ReadSplatmap(TerrainData data, int channel, float[,,] array = null)
|
|
{
|
|
CoordRect centerRect = CoordRect.Intersect(rect, new CoordRect(0, 0, data.alphamapResolution, data.alphamapResolution));
|
|
if (array == null)
|
|
{
|
|
array = data.GetAlphamaps(centerRect.offset.x, centerRect.offset.z, centerRect.size.x, centerRect.size.z);
|
|
}
|
|
Coord min = centerRect.Min;
|
|
Coord max = centerRect.Max;
|
|
for (int i = min.x; i < max.x; i++)
|
|
{
|
|
for (int j = min.z; j < max.z; j++)
|
|
{
|
|
this[i, j] = array[j - min.z, i - min.x, channel];
|
|
}
|
|
}
|
|
RemoveBorders(centerRect);
|
|
return array;
|
|
}
|
|
|
|
public static void AddSplatmaps(TerrainData data, Matrix[] matrices, int[] channels, float[] opacity, float[,,] array = null, float brushFallof = 0.5f)
|
|
{
|
|
int alphamapLayers = data.alphamapLayers;
|
|
bool[] array2 = new bool[alphamapLayers];
|
|
for (int i = 0; i < channels.Length; i++)
|
|
{
|
|
array2[channels[i]] = true;
|
|
}
|
|
float[] array3 = new float[alphamapLayers];
|
|
CoordRect c = new CoordRect(size: new Coord(data.alphamapResolution, data.alphamapResolution), offset: new Coord(0, 0));
|
|
CoordRect coordRect = CoordRect.Intersect(c, matrices[0].rect);
|
|
if (array == null)
|
|
{
|
|
array = data.GetAlphamaps(coordRect.offset.x, coordRect.offset.z, coordRect.size.x, coordRect.size.z);
|
|
}
|
|
Coord min = coordRect.Min;
|
|
Coord max = coordRect.Max;
|
|
for (int j = min.x; j < max.x; j++)
|
|
{
|
|
for (int k = min.z; k < max.z; k++)
|
|
{
|
|
float num = matrices[0].Fallof(j, k, brushFallof);
|
|
if (Mathf.Approximately(num, 0f))
|
|
{
|
|
continue;
|
|
}
|
|
for (int l = 0; l < alphamapLayers; l++)
|
|
{
|
|
array3[l] = array[k - min.z, j - min.x, l];
|
|
}
|
|
for (int m = 0; m < matrices.Length; m++)
|
|
{
|
|
matrices[m][j, k] = Mathf.Max(0f, matrices[m][j, k] - array3[channels[m]]);
|
|
}
|
|
for (int n = 0; n < matrices.Length; n++)
|
|
{
|
|
matrices[n][j, k] *= num * opacity[n];
|
|
}
|
|
float num2 = 0f;
|
|
for (int num3 = 0; num3 < matrices.Length; num3++)
|
|
{
|
|
num2 += matrices[num3][j, k];
|
|
}
|
|
if (num2 > 1f)
|
|
{
|
|
for (int num4 = 0; num4 < matrices.Length; num4++)
|
|
{
|
|
matrices[num4][j, k] /= num2;
|
|
}
|
|
num2 = 1f;
|
|
}
|
|
float num5 = 1f - num2;
|
|
for (int num6 = 0; num6 < alphamapLayers; num6++)
|
|
{
|
|
array3[num6] *= num5;
|
|
}
|
|
for (int num7 = 0; num7 < matrices.Length; num7++)
|
|
{
|
|
array3[channels[num7]] += matrices[num7][j, k];
|
|
}
|
|
for (int num8 = 0; num8 < alphamapLayers; num8++)
|
|
{
|
|
array[k - min.z, j - min.x, num8] = array3[num8];
|
|
}
|
|
}
|
|
}
|
|
data.SetAlphamaps(coordRect.offset.x, coordRect.offset.z, array);
|
|
}
|
|
|
|
public void ToTexture(Texture2D texture = null, Color[] colors = null, float rangeMin = 0f, float rangeMax = 1f, bool resizeTexture = false)
|
|
{
|
|
if (texture == null)
|
|
{
|
|
texture = new Texture2D(rect.size.x, rect.size.z);
|
|
}
|
|
if (resizeTexture)
|
|
{
|
|
texture.Resize(rect.size.x, rect.size.z);
|
|
}
|
|
CoordRect c = new CoordRect(size: new Coord(texture.width, texture.height), offset: new Coord(0, 0));
|
|
CoordRect coordRect = CoordRect.Intersect(c, rect);
|
|
if (colors == null || colors.Length != coordRect.size.x * coordRect.size.z)
|
|
{
|
|
colors = new Color[coordRect.size.x * coordRect.size.z];
|
|
}
|
|
Coord min = coordRect.Min;
|
|
Coord max = coordRect.Max;
|
|
for (int i = min.x; i < max.x; i++)
|
|
{
|
|
for (int j = min.z; j < max.z; j++)
|
|
{
|
|
float num = this[i, j];
|
|
num -= rangeMin;
|
|
num /= rangeMax - rangeMin;
|
|
float num2 = num * 256f;
|
|
int num3 = (int)num2;
|
|
float num4 = num2 - (float)num3;
|
|
float num5 = (float)num3 / 256f;
|
|
float num6 = (float)(num3 + 1) / 256f;
|
|
int num7 = i - min.x;
|
|
int num8 = j - min.z;
|
|
colors[num8 * (max.x - min.x) + num7] = new Color(num5, (!(num4 > 0.333f)) ? num5 : num6, (!(num4 > 0.666f)) ? num5 : num6);
|
|
}
|
|
}
|
|
texture.SetPixels(coordRect.offset.x, coordRect.offset.z, coordRect.size.x, coordRect.size.z, colors);
|
|
texture.Apply();
|
|
}
|
|
|
|
public void FromTexture(Texture2D texture, bool fillBorders = false)
|
|
{
|
|
CoordRect c = new CoordRect(size: new Coord(texture.width, texture.height), offset: new Coord(0, 0));
|
|
CoordRect centerRect = CoordRect.Intersect(c, rect);
|
|
Color[] pixels = texture.GetPixels(centerRect.offset.x, centerRect.offset.z, centerRect.size.x, centerRect.size.z);
|
|
Coord min = centerRect.Min;
|
|
Coord max = centerRect.Max;
|
|
for (int i = min.x; i < max.x; i++)
|
|
{
|
|
for (int j = min.z; j < max.z; j++)
|
|
{
|
|
int num = i - min.x;
|
|
int num2 = j - min.z;
|
|
Color color = pixels[num2 * (max.x - min.x) + num];
|
|
this[i, j] = (color.r + color.g + color.b) / 3f;
|
|
}
|
|
}
|
|
if (fillBorders)
|
|
{
|
|
RemoveBorders(centerRect);
|
|
}
|
|
}
|
|
|
|
public Texture2D SimpleToTexture(Texture2D texture = null, Color[] colors = null, float rangeMin = 0f, float rangeMax = 1f, string savePath = null)
|
|
{
|
|
if (texture == null)
|
|
{
|
|
texture = new Texture2D(rect.size.x, rect.size.z);
|
|
}
|
|
if (texture.width != rect.size.x || texture.height != rect.size.z)
|
|
{
|
|
texture.Resize(rect.size.x, rect.size.z);
|
|
}
|
|
if (colors == null || colors.Length != rect.size.x * rect.size.z)
|
|
{
|
|
colors = new Color[rect.size.x * rect.size.z];
|
|
}
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
float num = array[i];
|
|
num -= rangeMin;
|
|
num /= rangeMax - rangeMin;
|
|
colors[i] = new Color(num, num, num);
|
|
}
|
|
texture.SetPixels(colors);
|
|
texture.Apply();
|
|
return texture;
|
|
}
|
|
|
|
public void SimpleFromTexture(Texture2D texture)
|
|
{
|
|
ChangeRect(new CoordRect(rect.offset.x, rect.offset.z, texture.width, texture.height));
|
|
Color[] pixels = texture.GetPixels();
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
Color color = pixels[i];
|
|
array[i] = (color.r + color.g + color.b) / 3f;
|
|
}
|
|
}
|
|
|
|
public void RemoveBorders()
|
|
{
|
|
Coord min = rect.Min;
|
|
Coord coord = rect.Max - 1;
|
|
for (int i = min.x; i <= coord.x; i++)
|
|
{
|
|
SetPos(i, min.z);
|
|
array[pos] = nextZ;
|
|
}
|
|
for (int j = min.x; j <= coord.x; j++)
|
|
{
|
|
SetPos(j, coord.z);
|
|
array[pos] = prevZ;
|
|
}
|
|
for (int k = min.z; k <= coord.z; k++)
|
|
{
|
|
SetPos(min.x, k);
|
|
array[pos] = nextX;
|
|
}
|
|
for (int l = min.z; l <= coord.z; l++)
|
|
{
|
|
SetPos(coord.x, l);
|
|
array[pos] = prevX;
|
|
}
|
|
}
|
|
|
|
public void RemoveBorders(int borderMinX, int borderMinZ, int borderMaxX, int borderMaxZ)
|
|
{
|
|
Coord min = rect.Min;
|
|
Coord max = rect.Max;
|
|
if (borderMinZ != 0)
|
|
{
|
|
for (int i = min.x; i < max.x; i++)
|
|
{
|
|
float value = this[i, min.z + borderMinZ];
|
|
for (int j = min.z; j < min.z + borderMinZ; j++)
|
|
{
|
|
this[i, j] = value;
|
|
}
|
|
}
|
|
}
|
|
if (borderMaxZ != 0)
|
|
{
|
|
for (int k = min.x; k < max.x; k++)
|
|
{
|
|
float value2 = this[k, max.z - borderMaxZ];
|
|
for (int l = max.z - borderMaxZ; l < max.z; l++)
|
|
{
|
|
this[k, l] = value2;
|
|
}
|
|
}
|
|
}
|
|
if (borderMinX != 0)
|
|
{
|
|
for (int m = min.z; m < max.z; m++)
|
|
{
|
|
float value3 = this[min.x + borderMinX, m];
|
|
for (int n = min.x; n < min.x + borderMinX; n++)
|
|
{
|
|
this[n, m] = value3;
|
|
}
|
|
}
|
|
}
|
|
if (borderMaxX == 0)
|
|
{
|
|
return;
|
|
}
|
|
for (int num = min.z; num < max.z; num++)
|
|
{
|
|
float value4 = this[max.x - borderMaxX, num];
|
|
for (int num2 = max.x - borderMaxX; num2 < max.x; num2++)
|
|
{
|
|
this[num2, num] = value4;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void RemoveBorders(CoordRect centerRect)
|
|
{
|
|
RemoveBorders(Mathf.Max(0, centerRect.offset.x - rect.offset.x), Mathf.Max(0, centerRect.offset.z - rect.offset.z), Mathf.Max(0, rect.Max.x - centerRect.Max.x + 1), Mathf.Max(0, rect.Max.z - centerRect.Max.z + 1));
|
|
}
|
|
|
|
public Matrix Resize(CoordRect newRect, float smoothness = 1f, Matrix result = null)
|
|
{
|
|
int num = newRect.size.x / rect.size.x;
|
|
int num2 = rect.size.x / newRect.size.x;
|
|
if (num > 1 && !newRect.Divisible(num))
|
|
{
|
|
Debug.LogError(string.Concat("Matrix rect ", rect, " could not be upscaled to ", newRect, " with factor ", num));
|
|
}
|
|
if (num2 > 1 && !rect.Divisible(num2))
|
|
{
|
|
Debug.LogError(string.Concat("Matrix rect ", rect, " could not be downscaled to ", newRect, " with factor ", num2));
|
|
}
|
|
if (num > 1)
|
|
{
|
|
result = Upscale(num, result);
|
|
}
|
|
if (num2 > 1)
|
|
{
|
|
result = Downscale(num2, smoothness, result);
|
|
}
|
|
if (num <= 1 && num2 <= 1)
|
|
{
|
|
return Clone(result);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public Matrix Upscale(int factor, Matrix result = null)
|
|
{
|
|
if (result == null)
|
|
{
|
|
result = new Matrix(rect * factor);
|
|
}
|
|
result.ChangeRect(rect * factor);
|
|
if (factor == 1)
|
|
{
|
|
return Clone(result);
|
|
}
|
|
Coord min = rect.Min;
|
|
Coord coord = rect.Max - 1;
|
|
float num = 1f / (float)factor;
|
|
for (int i = min.x; i < coord.x; i++)
|
|
{
|
|
for (int j = min.z; j < coord.z; j++)
|
|
{
|
|
float a = this[i, j];
|
|
float a2 = this[i + 1, j];
|
|
float b = this[i, j + 1];
|
|
float b2 = this[i + 1, j + 1];
|
|
for (int k = 0; k < factor; k++)
|
|
{
|
|
for (int l = 0; l < factor; l++)
|
|
{
|
|
float t = (float)k * num;
|
|
float t2 = (float)l * num;
|
|
float a3 = Mathf.Lerp(a, b, t2);
|
|
float b3 = Mathf.Lerp(a2, b2, t2);
|
|
result[i * factor + k, j * factor + l] = Mathf.Lerp(a3, b3, t);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
result.RemoveBorders(0, 0, factor + 1, factor + 1);
|
|
return result;
|
|
}
|
|
|
|
public Matrix Downscale(int factor = 2, float smoothness = 1f, Matrix result = null)
|
|
{
|
|
if (!rect.Divisible(factor))
|
|
{
|
|
Debug.LogError(string.Concat("Matrix rect ", rect, " could not be downscaled with factor ", factor));
|
|
}
|
|
if (result == null)
|
|
{
|
|
result = new Matrix(rect / factor);
|
|
}
|
|
result.ChangeRect(rect / factor);
|
|
if (factor == 1)
|
|
{
|
|
return Clone(result);
|
|
}
|
|
Coord min = rect.Min;
|
|
Coord min2 = result.rect.Min;
|
|
Coord max = result.rect.Max;
|
|
if (smoothness < 0.0001f)
|
|
{
|
|
for (int i = min2.x; i < max.x; i++)
|
|
{
|
|
for (int j = min2.z; j < max.z; j++)
|
|
{
|
|
int x = (i - min2.x) * factor + min.x;
|
|
int z = (j - min2.z) * factor + min.z;
|
|
result[i, j] = this[x, z];
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
for (int k = min2.x; k < max.x; k++)
|
|
{
|
|
for (int l = min2.z; l < max.z; l++)
|
|
{
|
|
int num = (k - min2.x) * factor + min.x;
|
|
int num2 = (l - min2.z) * factor + min.z;
|
|
float num3 = 0f;
|
|
for (int m = num; m < num + factor; m++)
|
|
{
|
|
for (int n = num2; n < num2 + factor; n++)
|
|
{
|
|
num3 += this[m, n];
|
|
}
|
|
}
|
|
result[k, l] = num3 / (float)(factor * factor) * smoothness + this[num, num2] * (1f - smoothness);
|
|
}
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
public void Cavity(float strength)
|
|
{
|
|
Func<float, float, float, float> blurFn = delegate(float prev, float curr, float next)
|
|
{
|
|
float num2 = curr - (next + prev) / 2f;
|
|
return num2 * num2 * (float)((num2 > 0f) ? 1 : (-1)) * strength * 1000f;
|
|
};
|
|
Matrix matrix = new Matrix(rect);
|
|
matrix.Blur(blurFn, 1f, 1, this, true, false);
|
|
Matrix matrix2 = new Matrix(rect);
|
|
matrix2.Blur(blurFn, 1f, 1, this, false);
|
|
for (int num = 0; num < array.Length; num++)
|
|
{
|
|
array[num] = matrix.array[num] + matrix2.array[num];
|
|
}
|
|
}
|
|
|
|
public void OverBlur(int iterations = 20)
|
|
{
|
|
Matrix matrix = Clone();
|
|
for (int i = 1; i <= iterations; i++)
|
|
{
|
|
switch (i)
|
|
{
|
|
case 1:
|
|
case 2:
|
|
matrix.Blur();
|
|
break;
|
|
case 3:
|
|
matrix.Blur();
|
|
matrix.Blur();
|
|
break;
|
|
default:
|
|
{
|
|
int step = i - 2;
|
|
matrix.Blur(null, 0.666f, step);
|
|
break;
|
|
}
|
|
}
|
|
for (int j = 0; j < array.Length; j++)
|
|
{
|
|
float num = matrix.array[j] * (float)i;
|
|
float num2 = array[j];
|
|
array[j] = num2 + num + num2 * num;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Blur(Func<float, float, float, float> blurFn = null, float intensity = 0.666f, int step = 1, Matrix reference = null, bool horizontal = true, bool vertical = true)
|
|
{
|
|
Coord min = rect.Min;
|
|
Coord max = rect.Max;
|
|
if (reference == null)
|
|
{
|
|
reference = this;
|
|
}
|
|
int num = max.x - 1;
|
|
int num2 = max.z - 1;
|
|
if (horizontal)
|
|
{
|
|
for (int i = min.z; i <= num2; i++)
|
|
{
|
|
float num3 = reference[min.x, i];
|
|
float num4 = num3;
|
|
float num5 = num3;
|
|
float num6 = num3;
|
|
float num7 = num3;
|
|
for (int j = min.x + step; j <= num; j += step)
|
|
{
|
|
num6 = ((blurFn != null) ? blurFn(num5, num4, num3) : ((num5 + num3) / 2f));
|
|
num6 = num4 * (1f - intensity) + num6 * intensity;
|
|
num5 = num4;
|
|
num4 = num3;
|
|
try
|
|
{
|
|
num3 = reference[j + step * 2, i];
|
|
}
|
|
catch
|
|
{
|
|
num3 = reference[num, i];
|
|
}
|
|
if (step == 1)
|
|
{
|
|
this[j, i] = num6;
|
|
}
|
|
else
|
|
{
|
|
for (int k = 0; k < step; k++)
|
|
{
|
|
float num8 = 1f * (float)k / (float)step;
|
|
this[j - step + k, i] = num6 * num8 + num7 * (1f - num8);
|
|
}
|
|
}
|
|
num7 = num6;
|
|
}
|
|
}
|
|
}
|
|
if (!vertical)
|
|
{
|
|
return;
|
|
}
|
|
for (int l = min.x; l <= num; l++)
|
|
{
|
|
float num9 = reference[l, min.z];
|
|
float num10 = num9;
|
|
float num11 = num9;
|
|
float num12 = num9;
|
|
float num13 = num9;
|
|
for (int m = min.z + step; m <= num2; m += step)
|
|
{
|
|
num12 = ((blurFn != null) ? blurFn(num11, num10, num9) : ((num11 + num9) / 2f));
|
|
num12 = num10 * (1f - intensity) + num12 * intensity;
|
|
num11 = num10;
|
|
num10 = num9;
|
|
try
|
|
{
|
|
num9 = reference[l, m + step * 2];
|
|
}
|
|
catch
|
|
{
|
|
num9 = reference[l, num2];
|
|
}
|
|
if (step == 1)
|
|
{
|
|
this[l, m] = num12;
|
|
}
|
|
else
|
|
{
|
|
for (int n = 0; n < step; n++)
|
|
{
|
|
float num14 = 1f * (float)n / (float)step;
|
|
this[l, m - step + n] = num12 * num14 + num13 * (1f - num14);
|
|
}
|
|
}
|
|
num13 = num12;
|
|
}
|
|
}
|
|
}
|
|
|
|
public float GetOnTerrain(Vector2 worldPos, Terrain terrain)
|
|
{
|
|
float num = (worldPos.x - terrain.transform.position.x) / terrain.terrainData.size.x;
|
|
float num2 = (worldPos.y - terrain.transform.position.z) / terrain.terrainData.size.z;
|
|
int value = Mathf.RoundToInt(num * (float)rect.size.x + (float)rect.offset.x);
|
|
int value2 = Mathf.RoundToInt(num2 * (float)rect.size.z + (float)rect.offset.z);
|
|
value = Mathf.Clamp(value, rect.Min.x + 1, rect.Max.x - 1);
|
|
value2 = Mathf.Clamp(value2, rect.Min.z + 1, rect.Max.z - 1);
|
|
return this[value, value2];
|
|
}
|
|
|
|
public static void BlendLayers(Matrix[] matrices, float[] opacity)
|
|
{
|
|
Coord min = matrices[0].rect.Min;
|
|
Coord max = matrices[0].rect.Max;
|
|
for (int i = min.x; i < max.x; i++)
|
|
{
|
|
for (int j = min.z; j < max.z; j++)
|
|
{
|
|
float num = 0f;
|
|
for (int num2 = matrices.Length - 1; num2 >= 0; num2--)
|
|
{
|
|
float num3 = matrices[num2][i, j];
|
|
float num4 = Mathf.Clamp01(num + num3 - 1f);
|
|
matrices[num2][i, j] = num3 - num4;
|
|
num += num3 - num4;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public static void NormalizeLayers(Matrix[] matrices, float[] opacity)
|
|
{
|
|
Coord min = matrices[0].rect.Min;
|
|
Coord max = matrices[0].rect.Max;
|
|
for (int i = min.x; i < max.x; i++)
|
|
{
|
|
for (int j = min.z; j < max.z; j++)
|
|
{
|
|
float num = 0f;
|
|
for (int k = 0; k < matrices.Length; k++)
|
|
{
|
|
num += matrices[k][i, j];
|
|
}
|
|
if (num > 1f)
|
|
{
|
|
for (int l = 0; l < matrices.Length; l++)
|
|
{
|
|
matrices[l][i, j] /= num;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public float Fallof(int x, int z, float fallof)
|
|
{
|
|
if (fallof < 0f)
|
|
{
|
|
return 1f;
|
|
}
|
|
float num = (float)rect.size.x / 2f - 1f;
|
|
float num2 = ((float)x - ((float)rect.offset.x + num)) / num;
|
|
float num3 = (float)rect.size.z / 2f - 1f;
|
|
float num4 = ((float)z - ((float)rect.offset.z + num3)) / num3;
|
|
float num5 = Mathf.Sqrt(num2 * num2 + num4 * num4);
|
|
float num6 = Mathf.Clamp01((1f - num5) / (1f - fallof));
|
|
return 3f * num6 * num6 - 2f * num6 * num6 * num6;
|
|
}
|
|
|
|
public void Add(Matrix add)
|
|
{
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
array[i] += add.array[i];
|
|
}
|
|
}
|
|
|
|
public void Add(float add)
|
|
{
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
array[i] += add;
|
|
}
|
|
}
|
|
|
|
public void Subtract(Matrix m)
|
|
{
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
array[i] -= m.array[i];
|
|
}
|
|
}
|
|
|
|
public void InvSubtract(Matrix m)
|
|
{
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
array[i] = m.array[i] - array[i];
|
|
}
|
|
}
|
|
|
|
public void ClampSubtract(Matrix m)
|
|
{
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
array[i] = Mathf.Clamp01(array[i] - m.array[i]);
|
|
}
|
|
}
|
|
|
|
public void Multiply(Matrix m)
|
|
{
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
array[i] *= m.array[i];
|
|
}
|
|
}
|
|
|
|
public void Multiply(float m)
|
|
{
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
array[i] *= m;
|
|
}
|
|
}
|
|
|
|
public bool CheckRange(float min, float max)
|
|
{
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
if (array[i] < min || array[i] > max)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
public void Clear()
|
|
{
|
|
for (int i = 0; i < array.Length; i++)
|
|
{
|
|
array[i] = 0f;
|
|
}
|
|
}
|
|
}
|
|
}
|