Heroes_of_Hiis/Assets/Polaris - Low Poly Ecosystem/Polaris - Low Poly Terrain .../Runtime/Scripts/StampTool/GGeometryStamper.cs

372 lines
11 KiB
C#

#if GRIFFIN
using System.Collections.Generic;
using UnityEngine;
namespace Pinwheel.Griffin.StampTool
{
[System.Serializable]
[ExecuteInEditMode]
public class GGeometryStamper : MonoBehaviour
{
public enum GStampChannel
{
Elevation, Visibility
}
[SerializeField]
private bool enableTerrainMask = true;
public bool EnableTerrainMask
{
get
{
return enableTerrainMask;
}
set
{
enableTerrainMask = value;
}
}
[SerializeField]
private int groupId;
public int GroupId
{
get
{
return groupId;
}
set
{
groupId = value;
}
}
[SerializeField]
private Vector3 position;
public Vector3 Position
{
get
{
return position;
}
set
{
position = value;
transform.position = value;
}
}
[SerializeField]
private Quaternion rotation;
public Quaternion Rotation
{
get
{
return rotation;
}
set
{
rotation = value;
transform.rotation = value;
}
}
[SerializeField]
private Vector3 scale;
public Vector3 Scale
{
get
{
return scale;
}
set
{
scale = value;
transform.localScale = value;
}
}
[SerializeField]
private Texture2D stamp;
public Texture2D Stamp
{
get
{
return stamp;
}
set
{
stamp = value;
}
}
[SerializeField]
private GStampChannel channel;
public GStampChannel Channel
{
get
{
return channel;
}
set
{
channel = value;
}
}
[SerializeField]
private AnimationCurve falloff;
public AnimationCurve Falloff
{
get
{
return falloff;
}
set
{
falloff = value;
}
}
[SerializeField]
private bool inverseStamp;
public bool InverseStamp
{
get
{
return inverseStamp;
}
set
{
inverseStamp = value;
}
}
[SerializeField]
private bool useFalloffAsBlendFactor;
public bool UseFalloffAsBlendFactor
{
get
{
return useFalloffAsBlendFactor;
}
set
{
useFalloffAsBlendFactor = value;
}
}
[SerializeField]
private GStampOperation operation;
public GStampOperation Operation
{
get
{
return operation;
}
set
{
operation = value;
}
}
[SerializeField]
private float lerpFactor;
public float LerpFactor
{
get
{
return lerpFactor;
}
set
{
lerpFactor = Mathf.Clamp01(value);
}
}
[SerializeField]
private int additionalMeshResolution;
public int AdditionalMeshResolution
{
get
{
return additionalMeshResolution;
}
set
{
additionalMeshResolution = Mathf.Clamp(value, 0, 10);
}
}
private Texture2D falloffTexture;
public Rect Rect
{
get
{
Vector3[] quad = new Vector3[4];
GetQuad(quad);
Rect r = GUtilities.GetRectContainsPoints(quad);
return r;
}
}
private void Reset()
{
position = Vector3.zero;
rotation = Quaternion.identity;
scale = Vector3.one * 100;
stamp = null;
falloff = AnimationCurve.EaseInOut(0, 1, 1, 0);
inverseStamp = false;
useFalloffAsBlendFactor = true;
operation = GStampOperation.Max;
lerpFactor = 0.5f;
additionalMeshResolution = 0;
}
public void Apply()
{
if (falloffTexture != null)
Object.DestroyImmediate(falloffTexture);
Internal_UpdateFalloffTexture();
List<GStylizedTerrain> terrains = GUtilities.ExtractTerrainsFromOverlapTest(GCommon.OverlapTest(GroupId, GetQuad()));
foreach (GStylizedTerrain t in terrains)
{
DrawOnTexture(t);
}
foreach(GStylizedTerrain t in terrains)
{
UpdateTerrain(t);
}
foreach (GStylizedTerrain t in terrains)
{
t.MatchEdges();
}
}
private void DrawOnTexture(GStylizedTerrain t)
{
if (t.TerrainData == null)
return;
int heightMapResolution = t.TerrainData.Geometry.HeightMapResolution;
RenderTexture rt = new RenderTexture(heightMapResolution, heightMapResolution, 0, GGeometry.HeightMapRTFormat, RenderTextureReadWrite.Linear);
Internal_DrawOnTexture(t, rt);
Color[] oldHeightMapColors = t.TerrainData.Geometry.HeightMap.GetPixels();
RenderTexture.active = rt;
t.TerrainData.Geometry.HeightMap.ReadPixels(new Rect(0, 0, heightMapResolution, heightMapResolution), 0, 0);
t.TerrainData.Geometry.HeightMap.Apply();
RenderTexture.active = null;
Color[] newHeightMapColors = t.TerrainData.Geometry.HeightMap.GetPixels();
rt.Release();
Object.DestroyImmediate(rt);
List<Rect> dirtyRects = new List<Rect>(GCommon.CompareTerrainTexture(t.TerrainData.Geometry.ChunkGridSize, oldHeightMapColors, newHeightMapColors));
for (int i = 0; i < dirtyRects.Count; ++i)
{
t.TerrainData.Geometry.SetRegionDirty(dirtyRects[i]);
t.TerrainData.Foliage.SetTreeRegionDirty(dirtyRects[i]);
t.TerrainData.Foliage.SetGrassRegionDirty(dirtyRects[i]);
}
}
private void UpdateTerrain(GStylizedTerrain t)
{
t.TerrainData.SetDirty(GTerrainData.DirtyFlags.Geometry);
t.UpdateTreesPosition();
t.UpdateGrassPatches();
t.TerrainData.Foliage.ClearTreeDirtyRegions();
t.TerrainData.Foliage.ClearGrassDirtyRegions();
t.TerrainData.SetDirty(GTerrainData.DirtyFlags.Foliage);
}
public void Internal_DrawOnTexture(GStylizedTerrain t, RenderTexture rt)
{
GCommon.CopyToRT(t.TerrainData.Geometry.HeightMap, rt);
Vector3[] worldCorner = GetQuad();
Vector2[] uvCorners = new Vector2[worldCorner.Length];
for (int i = 0; i < uvCorners.Length; ++i)
{
uvCorners[i] = t.WorldPointToUV(worldCorner[i]);
}
Rect dirtyRect = GUtilities.GetRectContainsPoints(uvCorners);
if (!dirtyRect.Overlaps(new Rect(0, 0, 1, 1)))
return;
Vector3 normalizedPos = t.WorldPointToNormalized(Position);
float stampHeight = GUtilities.InverseLerpUnclamped(0, t.TerrainData.Geometry.Height, Scale.y);
Material mat = GInternalMaterials.StamperMaterial;
mat.SetTexture("_HeightMap", t.TerrainData.Geometry.HeightMap);
mat.SetTexture("_Stamp", Stamp);
mat.SetTexture("_Falloff", falloffTexture);
mat.SetInt("_Operation", (int)Operation);
mat.SetFloat("_LerpFactor", LerpFactor);
mat.SetFloat("_StampHeight", stampHeight);
mat.SetFloat("_StampPositionY", normalizedPos.y);
mat.SetFloat("_Inverse", InverseStamp ? 1 : 0);
mat.SetFloat("_UseFalloffAsBlendFactor", UseFalloffAsBlendFactor ? 1 : 0);
mat.SetFloat("_AdditionalMeshResolution", GCommon.SUB_DIV_STEP * AdditionalMeshResolution);
if (EnableTerrainMask)
{
mat.SetTexture("_TerrainMask", t.TerrainData.Mask.MaskMapOrDefault);
}
else
{
mat.SetTexture("_TerrainMask", Texture2D.blackTexture);
}
int pass = (int)Channel;
GCommon.DrawQuad(rt, uvCorners, mat, pass);
}
public void Internal_UpdateFalloffTexture()
{
falloffTexture = GCommon.CreateTextureFromCurve(Falloff, 256, 1);
}
public Vector3[] GetQuad()
{
Matrix4x4 matrix = Matrix4x4.TRS(Position, Rotation, Scale);
Vector3[] quad = new Vector3[4]
{
matrix.MultiplyPoint(new Vector3(-0.5f, 0, -0.5f)),
matrix.MultiplyPoint(new Vector3(-0.5f, 0, 0.5f)),
matrix.MultiplyPoint(new Vector3(0.5f, 0, 0.5f)),
matrix.MultiplyPoint(new Vector3(0.5f, 0, -0.5f))
};
return quad;
}
public void GetQuad(Vector3[] quad)
{
Matrix4x4 matrix = Matrix4x4.TRS(Position, Rotation, Scale);
quad[0] = matrix.MultiplyPoint(new Vector3(-0.5f, 0, -0.5f));
quad[1] = matrix.MultiplyPoint(new Vector3(-0.5f, 0, 0.5f));
quad[2] = matrix.MultiplyPoint(new Vector3(0.5f, 0, 0.5f));
quad[3] = matrix.MultiplyPoint(new Vector3(0.5f, 0, -0.5f));
}
public void GetBox(Vector3[] box)
{
Matrix4x4 matrix = Matrix4x4.TRS(Position, Rotation, Scale);
box[0] = matrix.MultiplyPoint(new Vector3(-0.5f, 0, -0.5f));
box[1] = matrix.MultiplyPoint(new Vector3(-0.5f, 0, 0.5f));
box[2] = matrix.MultiplyPoint(new Vector3(0.5f, 0, 0.5f));
box[3] = matrix.MultiplyPoint(new Vector3(0.5f, 0, -0.5f));
box[4] = matrix.MultiplyPoint(new Vector3(-0.5f, 1, -0.5f));
box[5] = matrix.MultiplyPoint(new Vector3(-0.5f, 1, 0.5f));
box[6] = matrix.MultiplyPoint(new Vector3(0.5f, 1, 0.5f));
box[7] = matrix.MultiplyPoint(new Vector3(0.5f, 1, -0.5f));
}
}
}
#endif