This commit is contained in:
CortexCore
2025-03-14 21:04:19 +08:00
parent ff8670c453
commit 757ffe79ee
1282 changed files with 104378 additions and 3 deletions

View File

@@ -0,0 +1,13 @@
#if GRIFFIN
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace Pinwheel.Griffin
{
public enum GAlbedoToVertexColorMode
{
None, Sharp, Smooth
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 400f8297c7702214bbf272e603499de0
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,568 @@
#if GRIFFIN
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Serialization;
using Unity.Collections;
using Pinwheel.Griffin.Rendering;
using Pinwheel.Griffin.Compression;
namespace Pinwheel.Griffin
{
public class GFoliage : ScriptableObject, ISerializationCallbackReceiver
{
[SerializeField]
private GTerrainData terrainData;
public GTerrainData TerrainData
{
get
{
return terrainData;
}
internal set
{
terrainData = value;
}
}
[SerializeField]
private GTreePrototypeGroup trees;
public GTreePrototypeGroup Trees
{
get
{
return trees;
}
set
{
trees = value;
}
}
[SerializeField]
private List<GTreeInstance> treeInstances;
public List<GTreeInstance> TreeInstances
{
get
{
if (treeInstances == null)
treeInstances = new List<GTreeInstance>();
return treeInstances;
}
set
{
treeInstances = value;
}
}
[SerializeField]
private GSnapMode treeSnapMode;
public GSnapMode TreeSnapMode
{
get
{
return treeSnapMode;
}
set
{
treeSnapMode = value;
}
}
[SerializeField]
private LayerMask treeSnapLayerMask;
public LayerMask TreeSnapLayerMask
{
get
{
return treeSnapLayerMask;
}
set
{
treeSnapLayerMask = value;
}
}
[SerializeField]
private GGrassPrototypeGroup grasses;
public GGrassPrototypeGroup Grasses
{
get
{
return grasses;
}
set
{
GGrassPrototypeGroup oldValue = grasses;
GGrassPrototypeGroup newValue = value;
grasses = newValue;
if (oldValue != newValue)
{
if (TerrainData != null)
{
TerrainData.InvokeGrassPrototypeGroupChanged();
}
}
}
}
[SerializeField]
private GSnapMode grassSnapMode;
public GSnapMode GrassSnapMode
{
get
{
return grassSnapMode;
}
set
{
grassSnapMode = value;
}
}
[SerializeField]
private LayerMask grassSnapLayerMask;
public LayerMask GrassSnapLayerMask
{
get
{
return grassSnapLayerMask;
}
set
{
grassSnapLayerMask = value;
}
}
[SerializeField]
private int patchGridSize;
public int PatchGridSize
{
get
{
return patchGridSize;
}
set
{
int oldValue = patchGridSize;
int newValue = Mathf.Clamp(value, 1, 20);
patchGridSize = newValue;
if (oldValue != newValue)
{
if (grassPatches != null)
{
ResampleGrassPatches();
}
if (TerrainData != null)
{
TerrainData.InvokeGrassPatchGridSizeChange();
}
}
}
}
[SerializeField]
private GGrassPatch[] grassPatches;
public GGrassPatch[] GrassPatches
{
get
{
if (grassPatches == null)
{
grassPatches = new GGrassPatch[PatchGridSize * PatchGridSize];
for (int x = 0; x < PatchGridSize; ++x)
{
for (int z = 0; z < patchGridSize; ++z)
{
GGrassPatch patch = new GGrassPatch(this, x, z);
grassPatches[GUtilities.To1DIndex(x, z, PatchGridSize)] = patch;
}
}
}
if (grassPatches.Length != PatchGridSize * PatchGridSize)
{
ResampleGrassPatches();
}
return grassPatches;
}
}
private List<Rect> treeDirtyRegions;
private List<Rect> TreeDirtyRegions
{
get
{
if (treeDirtyRegions == null)
{
treeDirtyRegions = new List<Rect>();
}
return treeDirtyRegions;
}
set
{
treeDirtyRegions = value;
}
}
private List<Rect> grassDirtyRegions;
private List<Rect> GrassDirtyRegions
{
get
{
if (grassDirtyRegions == null)
{
grassDirtyRegions = new List<Rect>();
}
return grassDirtyRegions;
}
set
{
grassDirtyRegions = value;
}
}
[SerializeField]
private bool enableInteractiveGrass;
public bool EnableInteractiveGrass
{
get
{
return enableInteractiveGrass;
}
set
{
enableInteractiveGrass = value;
}
}
[SerializeField]
private int vectorFieldMapResolution;
public int VectorFieldMapResolution
{
get
{
return vectorFieldMapResolution;
}
set
{
vectorFieldMapResolution = Mathf.Clamp(Mathf.ClosestPowerOfTwo(value), GCommon.TEXTURE_SIZE_MIN, GCommon.TEXTURE_SIZE_MAX);
}
}
[SerializeField]
private float bendSensitive;
public float BendSensitive
{
get
{
return bendSensitive;
}
set
{
bendSensitive = Mathf.Clamp01(value);
}
}
[SerializeField]
private float restoreSensitive;
public float RestoreSensitive
{
get
{
return restoreSensitive;
}
set
{
restoreSensitive = Mathf.Clamp01(value);
}
}
public int GrassInstanceCount
{
get
{
int count = 0;
for (int i = 0; i < GrassPatches.Length; ++i)
{
count += GrassPatches[i].Instances.Count;
}
return count;
}
}
public float grassVersion;
public const float GRASS_VERSION_COMPRESSED = 2020.1f;
public void Reset()
{
name = "Foliage";
TreeSnapMode = GRuntimeSettings.Instance.foliageDefault.treeSnapMode;
TreeSnapLayerMask = GRuntimeSettings.Instance.foliageDefault.treeSnapLayerMask;
GrassSnapMode = GRuntimeSettings.Instance.foliageDefault.grassSnapMode;
GrassSnapLayerMask = GRuntimeSettings.Instance.foliageDefault.grassSnapLayerMask;
PatchGridSize = GRuntimeSettings.Instance.foliageDefault.patchGridSize;
EnableInteractiveGrass = GRuntimeSettings.Instance.foliageDefault.enableInteractiveGrass;
VectorFieldMapResolution = GRuntimeSettings.Instance.foliageDefault.vectorFieldMapResolution;
BendSensitive = GRuntimeSettings.Instance.foliageDefault.bendSensitive;
RestoreSensitive = GRuntimeSettings.Instance.foliageDefault.restoreSensitive;
ClearGrassInstances();
ClearTreeInstances();
grassVersion = GVersionInfo.Number;
}
public void ResetFull()
{
Reset();
}
public void Refresh()
{
//if (Trees != null)
//{
// List<GTreePrototype> prototypes = Trees.Prototypes;
// //for (int i = 0; i < prototypes.Count; ++i)
// //{
// // prototypes[i].Refresh();
// //}
// RemoveTreeInstances(t => t.PrototypeIndex < 0 || t.PrototypeIndex >= Trees.Prototypes.Count);
//}
//if (Grasses != null)
//{
// for (int i = 0; i < GrassPatches.Length; ++i)
// {
// GrassPatches[i].RemoveInstances(g => g.PrototypeIndex < 0 || g.PrototypeIndex >= Grasses.Prototypes.Count);
// }
//}
}
private void ResampleGrassPatches()
{
List<GGrassInstance> grassInstances = new List<GGrassInstance>();
for (int i = 0; i < grassPatches.Length; ++i)
{
grassInstances.AddRange(grassPatches[i].Instances);
}
grassPatches = new GGrassPatch[PatchGridSize * PatchGridSize];
for (int x = 0; x < PatchGridSize; ++x)
{
for (int z = 0; z < patchGridSize; ++z)
{
int index = GUtilities.To1DIndex(x, z, PatchGridSize);
GGrassPatch patch = new GGrassPatch(this, x, z);
grassPatches[index] = patch;
}
}
AddGrassInstances(grassInstances);
}
public void AddGrassInstances(List<GGrassInstance> instances)
{
Rect[] uvRects = new Rect[GrassPatches.Length];
for (int r = 0; r < uvRects.Length; ++r)
{
uvRects[r] = GrassPatches[r].GetUvRange();
}
bool[] dirty = new bool[GrassPatches.Length];
for (int i = 0; i < instances.Count; ++i)
{
GGrassInstance grass = instances[i];
for (int r = 0; r < uvRects.Length; ++r)
{
if (uvRects[r].Contains(new Vector2(grass.position.x, grass.position.z)))
{
grassPatches[r].Instances.Add(grass);
dirty[r] = true;
break;
}
}
}
for (int i = 0; i < dirty.Length; ++i)
{
if (dirty[i] == true)
{
GrassPatches[i].RecalculateBounds();
GrassPatches[i].Changed();
}
}
}
public List<GGrassInstance> GetGrassInstances()
{
List<GGrassInstance> instances = new List<GGrassInstance>();
for (int i = 0; i < GrassPatches.Length; ++i)
{
instances.AddRange(GrassPatches[i].Instances);
}
return instances;
}
public void ClearGrassInstances()
{
for (int i = 0; i < GrassPatches.Length; ++i)
{
GrassPatches[i].ClearInstances();
}
}
public void SetTreeRegionDirty(Rect uvRect)
{
TreeDirtyRegions.Add(uvRect);
}
public void SetTreeRegionDirty(IEnumerable<Rect> uvRects)
{
TreeDirtyRegions.AddRange(uvRects);
}
public Rect[] GetTreeDirtyRegions()
{
return TreeDirtyRegions.ToArray();
}
public void ClearTreeDirtyRegions()
{
TreeDirtyRegions.Clear();
}
public void SetGrassRegionDirty(Rect uvRect)
{
GrassDirtyRegions.Add(uvRect);
}
public void SetGrassRegionDirty(IEnumerable<Rect> uvRects)
{
GrassDirtyRegions.AddRange(uvRects);
}
public Rect[] GetGrassDirtyRegions()
{
return GrassDirtyRegions.ToArray();
}
public void ClearGrassDirtyRegions()
{
GrassDirtyRegions.Clear();
}
public void CopyTo(GFoliage des)
{
des.Trees = Trees;
des.TreeSnapMode = TreeSnapMode;
des.TreeSnapLayerMask = TreeSnapLayerMask;
des.Grasses = Grasses;
des.GrassSnapMode = GrassSnapMode;
des.GrassSnapLayerMask = GrassSnapLayerMask;
des.PatchGridSize = PatchGridSize;
}
public void OnBeforeSerialize()
{
for (int i = 0; i < GrassPatches.Length; ++i)
{
GrassPatches[i].Serialize();
}
GCompressor.CleanUp();
}
public void OnAfterDeserialize()
{
for (int i = 0; i < GrassPatches.Length; ++i)
{
GrassPatches[i].Deserialize();
}
GCompressor.CleanUp();
}
public void Internal_UpgradeGrassSerializeVersion()
{
for (int i = 0; i < GrassPatches.Length; ++i)
{
GrassPatches[i].UpgradeSerializeVersion();
}
grassVersion = GVersionInfo.Number;
Debug.Log("Successfully upgrade grass serialize to newer version!");
}
public void GrassAllChanged()
{
for (int i = 0; i < GrassPatches.Length; ++i)
{
GrassPatches[i].Changed();
}
}
public void TreeAllChanged()
{
if (TerrainData != null)
{
TerrainData.InvokeTreeChanged();
}
}
public void AddTreeInstances(IEnumerable<GTreeInstance> newInstances)
{
TreeInstances.AddRange(newInstances);
TreeAllChanged();
}
public void RemoveTreeInstances(System.Predicate<GTreeInstance> condition)
{
int removedCount = TreeInstances.RemoveAll(condition);
if (removedCount > 0)
{
TreeAllChanged();
}
}
public void ClearTreeInstances()
{
TreeInstances.Clear();
TreeAllChanged();
}
public int GetTreeMemStats()
{
return TreeInstances.Count * GTreeInstance.GetStructSize();
}
public int GetGrassMemStats()
{
int memory = 0;
if (grassPatches != null)
{
for (int i = 0; i < grassPatches.Length; ++i)
{
if (grassPatches[i] != null)
{
memory += grassPatches[i].GetMemStats();
}
}
}
return memory;
}
public NativeArray<Vector2> GetTreesPositionArray(Allocator allocator = Allocator.TempJob)
{
List<GTreeInstance> trees = TreeInstances;
int treeCount = trees.Count;
NativeArray<Vector2> positions = new NativeArray<Vector2>(treeCount, allocator, NativeArrayOptions.UninitializedMemory);
Vector2 pos = Vector2.zero;
for (int i = 0; i < treeCount; ++i)
{
GTreeInstance t = trees[i];
pos.Set(t.position.x, t.position.z);
positions[i] = pos;
}
return positions;
}
}
}
#endif

View File

@@ -0,0 +1,14 @@
fileFormatVersion: 2
guid: 7b5acb73755bceb4d8263fff5b60c004
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences:
- terrainData: {instanceID: 0}
- trees: {fileID: 11400000, guid: 0af7475bfa20a88428c4fdadbd83fa37, type: 2}
- grasses: {fileID: 11400000, guid: a6542bf9c5c8f58429b0b70f81c0cb12, type: 2}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,97 @@
#if GRIFFIN
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
namespace Pinwheel.Griffin
{
public static class GFoliageExtensions
{
public static void AddGrassInstancesWithFilter(this GFoliage f, NativeArray<bool> filterNA, NativeArray<GPrototypeInstanceInfo> foliageInfoNA)
{
GGrassPatch[] patches = f.GrassPatches;
NativeArray<Rect> patchRectsNA = new NativeArray<Rect>(patches.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
for (int r = 0; r < patches.Length; ++r)
{
patchRectsNA[r] = patches[r].GetUvRange();
}
NativeArray<int> patchIndexNA = new NativeArray<int>(foliageInfoNA.Length, Allocator.TempJob, NativeArrayOptions.UninitializedMemory);
GPatchTestWithFilterJob job = new GPatchTestWithFilterJob()
{
patchRects = patchRectsNA,
filter = filterNA,
foliageInfo = foliageInfoNA,
patchIndex = patchIndexNA
};
JobHandle jHandle = job.Schedule(foliageInfoNA.Length, 100);
jHandle.Complete();
int[] patchIndex = patchIndexNA.ToArray();
GPrototypeInstanceInfo[] foliageInfo = foliageInfoNA.ToArray();
patchRectsNA.Dispose();
patchIndexNA.Dispose();
bool[] dirty = new bool[patches.Length];
for (int i = 0; i < foliageInfo.Length; ++i)
{
if (patchIndex[i] < 0)
continue;
patches[patchIndex[i]].Instances.Add(foliageInfo[i].ToGrassInstance());
dirty[patchIndex[i]] = true;
}
for (int i = 0; i < dirty.Length; ++i)
{
if (dirty[i] == true)
{
patches[i].RecalculateBounds();
patches[i].Changed();
}
}
}
#if GRIFFIN_BURST
[BurstCompile(CompileSynchronously = false)]
#endif
public struct GPatchTestWithFilterJob : IJobParallelFor
{
[ReadOnly]
public NativeArray<Rect> patchRects;
[ReadOnly]
public NativeArray<bool> filter;
[ReadOnly]
public NativeArray<GPrototypeInstanceInfo> foliageInfo;
[WriteOnly]
public NativeArray<int> patchIndex;
public void Execute(int index)
{
patchIndex[index] = -1;
if (filter[index] == false)
{
return;
}
GPrototypeInstanceInfo info = foliageInfo[index];
Vector2 pos = new Vector2(info.position.x, info.position.z);
int length = patchRects.Length;
for (int i = 0; i < length; ++i)
{
if (patchRects[i].Contains(pos))
{
patchIndex[index] = i;
return;
}
}
}
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 904d00621ec49474a970b363de76e74d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,591 @@
#if GRIFFIN
using System.Collections.Generic;
using UnityEngine;
using Type = System.Type;
namespace Pinwheel.Griffin
{
public class GGeometry : ScriptableObject
{
[System.Serializable]
public enum GStorageMode
{
SaveToAsset, GenerateOnEnable
}
public const string HEIGHT_MAP_NAME = "Height Map";
[SerializeField]
private GTerrainData terrainData;
public GTerrainData TerrainData
{
get
{
return terrainData;
}
internal set
{
terrainData = value;
}
}
[SerializeField]
internal float width;
public float Width
{
get
{
return width;
}
set
{
width = Mathf.Max(1, value);
}
}
[SerializeField]
internal float height;
public float Height
{
get
{
return height;
}
set
{
height = Mathf.Max(0, value);
}
}
[SerializeField]
internal float length;
public float Length
{
get
{
return length;
}
set
{
length = Mathf.Max(1, value);
}
}
public Vector3 Size
{
get
{
return new Vector3(Width, Height, Length);
}
}
[SerializeField]
private int heightMapResolution;
public int HeightMapResolution
{
get
{
return heightMapResolution;
}
set
{
int oldValue = heightMapResolution;
heightMapResolution = Mathf.Clamp(value, GCommon.TEXTURE_SIZE_MIN, GCommon.TEXTURE_SIZE_MAX);
if (oldValue != heightMapResolution)
{
ResampleHeightMap();
}
}
}
[SerializeField]
private Texture2D heightMap;
public Texture2D HeightMap
{
get
{
if (heightMap == null)
{
heightMap = GCommon.CreateTexture(HeightMapResolution, Color.clear, HeightMapFormat);
heightMap.filterMode = FilterMode.Bilinear;
heightMap.wrapMode = TextureWrapMode.Clamp;
heightMap.name = HEIGHT_MAP_NAME;
heightmapVersion = GVersionInfo.Number;
}
GCommon.TryAddObjectToAsset(heightMap, TerrainData);
if (heightMap.format != HeightMapFormat)
{
ReFormatHeightMap();
}
return heightMap;
}
}
[SerializeField]
private float heightmapVersion;
private const float HEIGHT_MAP_VERSION_ENCODE_RG = 246;
public static TextureFormat HeightMapFormat
{
get
{
return TextureFormat.RGBA32;
}
}
public static RenderTextureFormat HeightMapRTFormat
{
get
{
return RenderTextureFormat.ARGB32;
}
}
internal Texture2D subDivisionMap;
public Texture2D Internal_SubDivisionMap
{
get
{
if (subDivisionMap == null)
{
Internal_CreateNewSubDivisionMap();
}
return subDivisionMap;
}
}
[SerializeField]
private int meshBaseResolution;
public int MeshBaseResolution
{
get
{
return meshBaseResolution;
}
set
{
meshBaseResolution = Mathf.Min(meshResolution, Mathf.Clamp(value, 0, GCommon.MAX_MESH_BASE_RESOLUTION));
}
}
[SerializeField]
private int meshResolution;
public int MeshResolution
{
get
{
return meshResolution;
}
set
{
meshResolution = Mathf.Clamp(value, 0, GCommon.MAX_MESH_RESOLUTION);
}
}
[SerializeField]
private int chunkGridSize;
public int ChunkGridSize
{
get
{
return chunkGridSize;
}
set
{
chunkGridSize = Mathf.Max(1, value);
}
}
[SerializeField]
private int lodCount;
public int LODCount
{
get
{
return lodCount;
}
set
{
lodCount = Mathf.Clamp(value, 1, GCommon.MAX_LOD_COUNT);
}
}
[SerializeField]
private int displacementSeed;
public int DisplacementSeed
{
get
{
return displacementSeed;
}
set
{
displacementSeed = value;
}
}
[SerializeField]
private float displacementStrength;
public float DisplacementStrength
{
get
{
return displacementStrength;
}
set
{
displacementStrength = Mathf.Max(0, value);
}
}
[SerializeField]
private GAlbedoToVertexColorMode albedoToVertexColorMode;
public GAlbedoToVertexColorMode AlbedoToVertexColorMode
{
get
{
return albedoToVertexColorMode;
}
set
{
albedoToVertexColorMode = value;
}
}
[SerializeField]
private GStorageMode storageMode;
public GStorageMode StorageMode
{
get
{
return storageMode;
}
set
{
storageMode = value;
if (storageMode == GStorageMode.GenerateOnEnable)
{
TerrainData.GeometryData = null;
}
}
}
[SerializeField]
private bool allowTimeSlicedGeneration;
public bool AllowTimeSlicedGeneration
{
get
{
return allowTimeSlicedGeneration;
}
set
{
allowTimeSlicedGeneration = value;
}
}
[SerializeField]
private bool smoothNormal;
public bool SmoothNormal
{
get
{
return smoothNormal;
}
set
{
smoothNormal = value;
}
}
[SerializeField]
private bool useSmoothNormalMask;
public bool UseSmoothNormalMask
{
get
{
return useSmoothNormalMask;
}
set
{
useSmoothNormalMask = value;
}
}
[SerializeField]
private bool mergeUv;
public bool MergeUv
{
get
{
return mergeUv;
}
set
{
mergeUv = value;
}
}
private List<Rect> dirtyRegion;
private List<Rect> DirtyRegion
{
get
{
if (dirtyRegion == null)
{
dirtyRegion = new List<Rect>();
}
return dirtyRegion;
}
set
{
dirtyRegion = value;
}
}
public void Reset()
{
name = "Geometry";
Width = GRuntimeSettings.Instance.geometryDefault.width;
Height = GRuntimeSettings.Instance.geometryDefault.height;
Length = GRuntimeSettings.Instance.geometryDefault.length;
HeightMapResolution = GRuntimeSettings.Instance.geometryDefault.heightMapResolution;
MeshResolution = GRuntimeSettings.Instance.geometryDefault.meshResolution;
MeshBaseResolution = GRuntimeSettings.Instance.geometryDefault.meshBaseResolution;
ChunkGridSize = GRuntimeSettings.Instance.geometryDefault.chunkGridSize;
LODCount = GRuntimeSettings.Instance.geometryDefault.lodCount;
DisplacementSeed = GRuntimeSettings.Instance.geometryDefault.displacementSeed;
DisplacementStrength = GRuntimeSettings.Instance.geometryDefault.displacementStrength;
AlbedoToVertexColorMode = GRuntimeSettings.Instance.geometryDefault.albedoToVertexColorMode;
StorageMode = GRuntimeSettings.Instance.geometryDefault.storageMode;
AllowTimeSlicedGeneration = GRuntimeSettings.Instance.geometryDefault.allowTimeSlicedGeneration;
SmoothNormal = GRuntimeSettings.Instance.geometryDefault.smoothNormal;
UseSmoothNormalMask = GRuntimeSettings.Instance.geometryDefault.useSmoothNormalMask;
MergeUv = GRuntimeSettings.Instance.geometryDefault.mergeUv;
}
public void ResetFull()
{
Reset();
GCommon.FillTexture(HeightMap, Color.clear);
SetRegionDirty(GCommon.UnitRect);
TerrainData.SetDirty(GTerrainData.DirtyFlags.GeometryTimeSliced);
}
private void ResampleHeightMap()
{
if (heightMap == null)
return;
Texture2D tmp = GCommon.CreateTexture(HeightMapResolution, Color.clear, HeightMapFormat);
RenderTexture rt = new RenderTexture(HeightMapResolution, HeightMapResolution, 32, HeightMapRTFormat);
GCommon.CopyTexture(heightMap, tmp);
tmp.name = heightMap.name;
tmp.filterMode = heightMap.filterMode;
tmp.wrapMode = heightMap.wrapMode;
Object.DestroyImmediate(heightMap, true);
heightMap = tmp;
GCommon.TryAddObjectToAsset(heightMap, TerrainData);
Internal_CreateNewSubDivisionMap();
SetRegionDirty(GCommon.UnitRect);
}
private void ReFormatHeightMap()
{
if (heightMap == null)
return;
if (heightmapVersion < HEIGHT_MAP_VERSION_ENCODE_RG)
{
Texture2D tmp = GCommon.CreateTexture(HeightMapResolution, Color.clear, HeightMapFormat);
RenderTexture rt = new RenderTexture(HeightMapResolution, HeightMapResolution, 32, HeightMapRTFormat);
Material mat = GInternalMaterials.HeightmapConverterEncodeRGMaterial;
mat.SetTexture("_MainTex", heightMap);
GCommon.DrawQuad(rt, GCommon.FullRectUvPoints, mat, 0);
GCommon.CopyFromRT(tmp, rt);
rt.Release();
Object.DestroyImmediate(rt);
tmp.name = heightMap.name;
tmp.filterMode = heightMap.filterMode;
tmp.wrapMode = heightMap.wrapMode;
Object.DestroyImmediate(heightMap, true);
heightMap = tmp;
GCommon.TryAddObjectToAsset(heightMap, TerrainData);
heightmapVersion = HEIGHT_MAP_VERSION_ENCODE_RG;
Debug.Log("Polaris auto upgrade: Converted Height Map from RGBAFloat to RGBA32.");
}
}
internal void Internal_CreateNewSubDivisionMap()
{
if (subDivisionMap != null)
{
if (subDivisionMap.width != GCommon.SUB_DIV_MAP_RESOLUTION ||
subDivisionMap.height != GCommon.SUB_DIV_MAP_RESOLUTION)
Object.DestroyImmediate(subDivisionMap);
}
if (subDivisionMap == null)
{
subDivisionMap = new Texture2D(GCommon.SUB_DIV_MAP_RESOLUTION, GCommon.SUB_DIV_MAP_RESOLUTION, TextureFormat.RGBA32, false);
}
int resolution = GCommon.SUB_DIV_MAP_RESOLUTION;
RenderTexture rt = new RenderTexture(resolution, resolution, 0, RenderTextureFormat.ARGB32);
Material mat = GInternalMaterials.SubDivisionMapMaterial;
Graphics.Blit(HeightMap, rt, mat);
GCommon.CopyFromRT(subDivisionMap, rt);
rt.Release();
Object.DestroyImmediate(rt);
}
internal void Internal_CreateNewSubDivisionMap(Texture altHeightMap)
{
if (subDivisionMap != null)
{
if (subDivisionMap.width != GCommon.SUB_DIV_MAP_RESOLUTION ||
subDivisionMap.height != GCommon.SUB_DIV_MAP_RESOLUTION)
Object.DestroyImmediate(subDivisionMap);
}
if (subDivisionMap == null)
{
subDivisionMap = new Texture2D(GCommon.SUB_DIV_MAP_RESOLUTION, GCommon.SUB_DIV_MAP_RESOLUTION, TextureFormat.ARGB32, false);
}
int resolution = GCommon.SUB_DIV_MAP_RESOLUTION;
RenderTexture rt = new RenderTexture(resolution, resolution, 0, RenderTextureFormat.ARGB32);
Material mat = GInternalMaterials.SubDivisionMapMaterial;
Graphics.Blit(altHeightMap, rt, mat);
GCommon.CopyFromRT(subDivisionMap, rt);
rt.Release();
Object.DestroyImmediate(rt);
}
public void CleanUp()
{
int count = 0;
List<Vector3Int> keys = TerrainData.GeometryData.GetKeys();
for (int i = 0; i < keys.Count; ++i)
{
bool delete = false;
try
{
int indexX = keys[i].x;
int indexY = keys[i].y;
int lod = keys[i].z;
if (indexX >= ChunkGridSize || indexY >= ChunkGridSize)
{
delete = true;
}
else if (lod >= LODCount)
{
delete = true;
}
else
{
delete = false;
}
}
catch
{
delete = false;
}
if (delete)
{
count += 1;
TerrainData.GeometryData.DeleteMesh(keys[i]);
}
}
if (count > 0)
{
Debug.Log(string.Format("Deleted {0} object{1} from generated data!", count, count > 1 ? "s" : ""));
}
}
public void SetRegionDirty(Rect uvRect)
{
DirtyRegion.Add(uvRect);
}
public void SetRegionDirty(IEnumerable<Rect> uvRects)
{
DirtyRegion.AddRange(uvRects);
}
public Rect[] GetDirtyRegions()
{
return DirtyRegion.ToArray();
}
public void ClearDirtyRegions()
{
DirtyRegion.Clear();
}
public void CopyTo(GGeometry des)
{
des.Width = Width;
des.Height = Height;
des.Length = Length;
des.HeightMapResolution = HeightMapResolution;
des.MeshResolution = MeshResolution;
des.MeshBaseResolution = MeshBaseResolution;
des.ChunkGridSize = ChunkGridSize;
des.LODCount = LODCount;
des.DisplacementSeed = DisplacementSeed;
des.DisplacementStrength = DisplacementStrength;
des.AlbedoToVertexColorMode = AlbedoToVertexColorMode;
des.StorageMode = StorageMode;
des.AllowTimeSlicedGeneration = AllowTimeSlicedGeneration;
}
public Vector4 GetDecodedHeightMapSample(Vector2 uv)
{
Vector4 c = HeightMap.GetPixelBilinear(uv.x, uv.y);
Vector2 encodedHeight = new Vector2(c.x, c.y);
float decodedHeight = GCommon.DecodeTerrainHeight(encodedHeight);
c.x = decodedHeight;
c.y = decodedHeight;
return c;
}
public float GetHeightMapMemoryStats()
{
if (heightMap == null)
return 0;
return heightMap.width * heightMap.height * 4;
}
public void RemoveHeightMap()
{
if (heightMap != null)
{
GUtilities.DestroyObject(heightMap);
}
}
public float[,] GetHeights()
{
int res = HeightMapResolution;
float[,] samples = new float[res, res];
Vector4 color;
for (int z = 0; z < res; ++z)
{
for (int x = 0; x< res; ++x)
{
color = HeightMap.GetPixel(x, z);
float h = GCommon.DecodeTerrainHeight(color);
samples[z, x] = h;
}
}
return samples;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: da65cc640ca49214eaaf69531b38de16
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,78 @@
#if GRIFFIN
using UnityEngine;
namespace Pinwheel.Griffin
{
[System.Serializable]
public struct GGrassInstance
{
[SerializeField]
internal int prototypeIndex;
public int PrototypeIndex
{
get
{
return prototypeIndex;
}
set
{
prototypeIndex = value;
}
}
[SerializeField]
internal Vector3 position;
public Vector3 Position
{
get
{
return position;
}
set
{
position = value;
}
}
[SerializeField]
internal Quaternion rotation;
public Quaternion Rotation
{
get
{
return rotation;
}
set
{
rotation = value;
}
}
[SerializeField]
internal Vector3 scale;
public Vector3 Scale
{
get
{
return scale;
}
set
{
scale = value;
}
}
public static GGrassInstance Create(int prototypeIndex)
{
GGrassInstance instance = new GGrassInstance();
instance.PrototypeIndex = prototypeIndex;
instance.Position = Vector3.zero;
instance.Rotation = Quaternion.identity;
instance.Scale = Vector3.one;
return instance;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: a8351d78df2822943bfaa51a9d02196d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,359 @@
#if GRIFFIN
using System.Collections.Generic;
using UnityEngine;
using Unity.Collections;
using Pinwheel.Griffin.Rendering;
using Pinwheel.Griffin.Compression;
using System;
using UnityEngine.Serialization;
namespace Pinwheel.Griffin
{
[System.Serializable]
public class GGrassPatch
{
[SerializeField]
private GFoliage foliage;
public GFoliage Foliage
{
get
{
return foliage;
}
private set
{
foliage = value;
}
}
[SerializeField]
private Vector2 index;
public Vector2 Index
{
get
{
return index;
}
set
{
index = value;
}
}
#pragma warning disable 0649
//Old container that get serialized as raw values and should be retired for now
//However, it should still be here to prevent data lost when upgrading from lower version
//This container will be empty after the manual upgrade
[SerializeField]
private List<GGrassInstance> instances;
#pragma warning restore 0649
internal int InstanceCount
{
get
{
if (instances_NonSerialized == null)
return 0;
else
return instances_NonSerialized.Count;
}
}
[NonSerialized]
private List<GGrassInstance> instances_NonSerialized;
internal List<GGrassInstance> Instances
{
get
{
if (instances_NonSerialized == null)
{
instances_NonSerialized = new List<GGrassInstance>();
}
return instances_NonSerialized;
}
set
{
instances_NonSerialized = value;
}
}
private bool requireFullUpdate;
internal bool RequireFullUpdate
{
get
{
return requireFullUpdate;
}
set
{
requireFullUpdate = value;
}
}
[SerializeField]
internal Bounds bounds;
public Bounds Bounds
{
get
{
return bounds;
}
private set
{
bounds = value;
}
}
[SerializeField]
private int instanceCountSerializeData;
[SerializeField]
private byte[] prototypeIndexSerializeData;
[SerializeField]
private byte[] positionSerializeData;
[SerializeField]
private byte[] rotationSerializeData;
[SerializeField]
private byte[] scaleSerializeData;
internal GGrassPatch(GFoliage owner, int indexX, int indexY)
{
foliage = owner;
Index = new Vector2(indexX, indexY);
}
public void Changed()
{
if (Foliage != null && Foliage.TerrainData != null)
{
Foliage.TerrainData.InvokeGrassChange(Index);
}
}
public void AddInstances(IEnumerable<GGrassInstance> newInstances)
{
Instances.AddRange(newInstances);
RecalculateBounds();
Changed();
}
public int RemoveInstances(Predicate<GGrassInstance> match)
{
int count = Instances.RemoveAll(match);
if (count > 0)
{
RecalculateBounds();
Changed();
}
return count;
}
public void ClearInstances()
{
Instances.Clear();
RecalculateBounds();
Changed();
}
public Rect GetUvRange()
{
return GCommon.GetUvRange(foliage.PatchGridSize, (int)Index.x, (int)Index.y);
}
public void RecalculateBounds()
{
if (Instances.Count == 0)
{
Rect r = GetUvRange();
Vector3 center = new Vector3(r.x, 0, r.y);
Vector3 size = Vector3.zero;
Bounds b = new Bounds();
b.center = center;
b.size = size;
Bounds = b;
}
else
{
float minX = float.MaxValue;
float maxX = float.MinValue;
float minY = float.MaxValue;
float maxY = float.MinValue;
float minZ = float.MaxValue;
float maxZ = float.MinValue;
int instanceCount = Instances.Count;
for (int i = 0; i < instanceCount; ++i)
{
Vector3 pos = Instances[i].Position;
minX = Mathf.Min(minX, pos.x);
maxX = Mathf.Max(maxX, pos.x);
minY = Mathf.Min(minY, pos.y);
maxY = Mathf.Max(maxY, pos.y);
minZ = Mathf.Min(minZ, pos.z);
maxZ = Mathf.Max(maxZ, pos.z);
}
Vector3 p = Vector3.Lerp(
new Vector3(minX, minY, minZ),
new Vector3(maxX, maxY, maxZ),
0.5f);
Vector3 s = new Vector3(
maxX - minX,
Mathf.Max(0.001f, maxY - minY),
maxZ - minZ);
Bounds = new Bounds(p, s);
}
}
internal void Serialize()
{
int count = Instances.Count;
int[] protoIndices = new int[count];
float[] positions = new float[count * 3];
float[] rotations = new float[count * 4];
float[] scales = new float[count * 3];
for (int i = 0; i < count; ++i)
{
GGrassInstance grass = Instances[i];
protoIndices[i] = grass.prototypeIndex;
positions[i * 3 + 0] = grass.position.x;
positions[i * 3 + 1] = grass.position.y;
positions[i * 3 + 2] = grass.position.z;
rotations[i * 4 + 0] = grass.rotation.x;
rotations[i * 4 + 1] = grass.rotation.y;
rotations[i * 4 + 2] = grass.rotation.z;
rotations[i * 4 + 3] = grass.rotation.w;
scales[i * 3 + 0] = grass.scale.x;
scales[i * 3 + 1] = grass.scale.y;
scales[i * 3 + 2] = grass.scale.z;
}
if (prototypeIndexSerializeData == null || prototypeIndexSerializeData.Length != Buffer.ByteLength(protoIndices))
{
prototypeIndexSerializeData = new byte[Buffer.ByteLength(protoIndices)];
}
Buffer.BlockCopy(protoIndices, 0, prototypeIndexSerializeData, 0, prototypeIndexSerializeData.Length);
prototypeIndexSerializeData = GCompressor.Compress(prototypeIndexSerializeData);
if (positionSerializeData == null || positionSerializeData.Length != Buffer.ByteLength(positions))
{
positionSerializeData = new byte[Buffer.ByteLength(positions)];
}
Buffer.BlockCopy(positions, 0, positionSerializeData, 0, positionSerializeData.Length);
positionSerializeData = GCompressor.Compress(positionSerializeData);
if (rotationSerializeData == null || rotationSerializeData.Length != Buffer.ByteLength(rotations))
{
rotationSerializeData = new byte[Buffer.ByteLength(rotations)];
}
Buffer.BlockCopy(rotations, 0, rotationSerializeData, 0, rotationSerializeData.Length);
rotationSerializeData = GCompressor.Compress(rotationSerializeData);
if (scaleSerializeData == null || scaleSerializeData.Length != Buffer.ByteLength(scales))
{
scaleSerializeData = new byte[Buffer.ByteLength(scales)];
}
Buffer.BlockCopy(scales, 0, scaleSerializeData, 0, scaleSerializeData.Length);
scaleSerializeData = GCompressor.Compress(scaleSerializeData);
instanceCountSerializeData = count;
}
internal void Deserialize()
{
if (prototypeIndexSerializeData != null &&
positionSerializeData != null &&
rotationSerializeData != null &&
scaleSerializeData != null)
{
prototypeIndexSerializeData = GCompressor.Decompress(prototypeIndexSerializeData, sizeof(int) * instanceCountSerializeData);
positionSerializeData = GCompressor.Decompress(positionSerializeData, sizeof(float) * 3 * instanceCountSerializeData);
rotationSerializeData = GCompressor.Decompress(rotationSerializeData, sizeof(float) * 4 * instanceCountSerializeData);
scaleSerializeData = GCompressor.Decompress(scaleSerializeData, sizeof(float) * 3 * instanceCountSerializeData);
int[] indices = new int[prototypeIndexSerializeData.Length / sizeof(int)];
float[] positions = new float[positionSerializeData.Length / sizeof(float)];
float[] rotations = new float[rotationSerializeData.Length / sizeof(float)];
float[] scales = new float[scaleSerializeData.Length / sizeof(float)];
Buffer.BlockCopy(prototypeIndexSerializeData, 0, indices, 0, prototypeIndexSerializeData.Length);
Buffer.BlockCopy(positionSerializeData, 0, positions, 0, positionSerializeData.Length);
Buffer.BlockCopy(rotationSerializeData, 0, rotations, 0, rotationSerializeData.Length);
Buffer.BlockCopy(scaleSerializeData, 0, scales, 0, scaleSerializeData.Length);
int instanceCount = indices.Length;
Instances.Clear();
for (int i = 0; i < instanceCount; ++i)
{
GGrassInstance grass = GGrassInstance.Create(indices[i]);
grass.position = new Vector3(
positions[i * 3 + 0],
positions[i * 3 + 1],
positions[i * 3 + 2]);
grass.rotation = new Quaternion(
rotations[i * 4 + 0],
rotations[i * 4 + 1],
rotations[i * 4 + 2],
rotations[i * 4 + 3]);
grass.scale = new Vector3(
scales[i * 3 + 0],
scales[i * 3 + 1],
scales[i * 3 + 2]);
Instances.Add(grass);
}
}
}
internal void UpgradeSerializeVersion()
{
//v250: Compressed serialization
if (instances != null && instances.Count > 0)
{
if (instances_NonSerialized != null)
{
instances_NonSerialized.AddRange(instances);
RecalculateBounds();
Changed();
}
}
}
public int GetMemStats()
{
int mem = 0;
if (prototypeIndexSerializeData != null)
{
mem += prototypeIndexSerializeData.Length;
mem += positionSerializeData.Length;
mem += rotationSerializeData.Length;
mem += scaleSerializeData.Length;
}
return mem;
}
public NativeArray<Vector2> GetGrassPositionArray(Allocator allocator = Allocator.TempJob)
{
int instanceCount = InstanceCount;
List<GGrassInstance> instances = Instances;
NativeArray<Vector2> positions = new NativeArray<Vector2>(instanceCount, allocator, NativeArrayOptions.UninitializedMemory);
Vector2 pos = Vector2.zero;
for (int i = 0; i < instanceCount; ++i)
{
GGrassInstance g = instances[i];
pos.Set(g.position.x, g.position.z);
positions[i] = pos;
}
return positions;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: fdd540a19ffbded44b9fb5512ac97475
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,328 @@
#if GRIFFIN
using UnityEngine;
using UnityEngine.Rendering;
namespace Pinwheel.Griffin
{
[System.Serializable]
public class GGrassPrototype
{
[SerializeField]
private Texture2D texture;
public Texture2D Texture
{
get
{
return texture;
}
set
{
texture = value;
}
}
[SerializeField]
private GameObject prefab;
public GameObject Prefab
{
get
{
return prefab;
}
set
{
prefab = value;
RefreshDetailObjectSettings();
}
}
[SerializeField]
internal Vector3 size;
public Vector3 Size
{
get
{
return size;
}
set
{
size = value;
}
}
[SerializeField]
internal int layer;
public int Layer
{
get
{
return layer;
}
set
{
layer = value;
}
}
[SerializeField]
private GGrassShape shape;
public GGrassShape Shape
{
get
{
return shape;
}
set
{
shape = value;
}
}
[SerializeField]
private Mesh customMesh;
public Mesh CustomMesh
{
get
{
return customMesh;
}
set
{
customMesh = value;
}
}
[SerializeField]
private Mesh detailMesh;
public Mesh DetailMesh
{
get
{
return detailMesh;
}
private set
{
detailMesh = value;
}
}
[SerializeField]
private Material detailMaterial;
public Material DetailMaterial
{
get
{
return detailMaterial;
}
private set
{
detailMaterial = value;
}
}
[SerializeField]
internal ShadowCastingMode shadowCastingMode;
public ShadowCastingMode ShadowCastingMode
{
get
{
return shadowCastingMode;
}
set
{
shadowCastingMode = value;
}
}
[SerializeField]
internal bool receiveShadow;
public bool ReceiveShadow
{
get
{
return receiveShadow;
}
set
{
receiveShadow = value;
}
}
[SerializeField]
private bool alignToSurface;
public bool AlignToSurface
{
get
{
return alignToSurface;
}
set
{
alignToSurface = value;
}
}
[SerializeField]
internal float pivotOffset;
public float PivotOffset
{
get
{
return pivotOffset;
}
set
{
pivotOffset = Mathf.Clamp(value, -1, 1);
}
}
[SerializeField]
private float bendFactor = 1;
public float BendFactor
{
get
{
return bendFactor;
}
set
{
bendFactor = Mathf.Max(0, value);
}
}
[SerializeField]
private Color color = Color.white;
public Color Color
{
get
{
return color;
}
set
{
color = value;
}
}
[SerializeField]
private bool isBillboard;
public bool IsBillboard
{
get
{
return isBillboard;
}
set
{
isBillboard = value;
}
}
public static GGrassPrototype Create(Texture2D tex)
{
GGrassPrototype prototype = new GGrassPrototype();
prototype.Shape = GGrassShape.Quad;
prototype.Texture = tex;
prototype.ShadowCastingMode = ShadowCastingMode.On;
prototype.ReceiveShadow = true;
prototype.Size = Vector3.one;
prototype.Layer = LayerMask.NameToLayer("Default");
prototype.AlignToSurface = false;
prototype.PivotOffset = 0;
prototype.BendFactor = 1;
prototype.Color = Color.white;
return prototype;
}
public static GGrassPrototype Create(GameObject prefab)
{
GGrassPrototype prototype = new GGrassPrototype();
prototype.Shape = GGrassShape.DetailObject;
prototype.Prefab = prefab;
prototype.Size = Vector3.one;
prototype.Layer = LayerMask.NameToLayer("Default");
prototype.AlignToSurface = false;
prototype.PivotOffset = 0;
prototype.BendFactor = 1;
prototype.Color = Color.white;
return prototype;
}
public Mesh GetBaseMesh()
{
if (Shape == GGrassShape.DetailObject)
{
return DetailMesh;
}
if (Shape == GGrassShape.CustomMesh)
{
return CustomMesh != null ? CustomMesh : GRuntimeSettings.Instance.foliageRendering.GetGrassMesh(GGrassShape.Quad);
}
else
{
return GRuntimeSettings.Instance.foliageRendering.GetGrassMesh(Shape);
}
}
public void RefreshDetailObjectSettings()
{
if (Prefab == null)
return;
MeshFilter mf = Prefab.GetComponentInChildren<MeshFilter>();
MeshRenderer mr = Prefab.GetComponentInChildren<MeshRenderer>();
if (mf != null)
{
DetailMesh = mf.sharedMesh;
}
if (mr != null)
{
DetailMaterial = mr.sharedMaterial;
}
}
public static explicit operator GGrassPrototype(DetailPrototype p)
{
GGrassPrototype proto = new GGrassPrototype();
proto.Color = p.healthyColor;
proto.Shape = p.usePrototypeMesh ? GGrassShape.DetailObject : GGrassShape.Quad;
proto.Texture = p.prototypeTexture;
proto.Prefab = p.prototype;
proto.Size = new Vector3(p.maxWidth, p.maxHeight, p.maxWidth);
proto.Layer = LayerMask.NameToLayer("Default");
proto.AlignToSurface = false;
proto.BendFactor = 1;
proto.IsBillboard = p.renderMode == DetailRenderMode.GrassBillboard;
return proto;
}
public static explicit operator DetailPrototype(GGrassPrototype p)
{
DetailPrototype proto = new DetailPrototype();
proto.usePrototypeMesh = p.Shape == GGrassShape.DetailObject;
proto.prototypeTexture = p.Texture;
proto.prototype = p.Prefab;
proto.minWidth = p.size.x;
proto.maxWidth = p.size.x * 2;
proto.minHeight = p.size.y;
proto.maxHeight = p.size.y * 2;
proto.healthyColor = p.color;
if (p.IsBillboard && p.Shape != GGrassShape.DetailObject)
proto.renderMode = DetailRenderMode.GrassBillboard;
return proto;
}
public bool Equals(DetailPrototype detailPrototype)
{
bool modeEqual =
(Shape == GGrassShape.Quad && !detailPrototype.usePrototypeMesh) ||
(Shape == GGrassShape.DetailObject && detailPrototype.usePrototypeMesh);
return
modeEqual &&
Texture == detailPrototype.prototypeTexture &&
Prefab == detailPrototype.prototype &&
Size == new Vector3(detailPrototype.maxWidth, detailPrototype.maxHeight, detailPrototype.maxWidth);
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 96bda82f18917ee469871bc317ae9b8d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,54 @@
#if GRIFFIN
using System.Collections.Generic;
using UnityEngine;
namespace Pinwheel.Griffin
{
[CreateAssetMenu(fileName = "Grass Prototype Group", menuName = "Polaris/Grass Prototype Group")]
public class GGrassPrototypeGroup : ScriptableObject
{
[SerializeField]
private List<GGrassPrototype> prototypes;
public List<GGrassPrototype> Prototypes
{
get
{
if (prototypes == null)
prototypes = new List<GGrassPrototype>();
return prototypes;
}
set
{
prototypes = value;
}
}
[SerializeField]
private bool isSampleAsset;
public bool IsSampleAsset => isSampleAsset;
public bool Equals(DetailPrototype[] detailPrototypes)
{
if (Prototypes.Count != detailPrototypes.Length)
return false;
for (int i = 0; i < Prototypes.Count; ++i)
{
if (!Prototypes[i].Equals(detailPrototypes[i]))
return false;
}
return true;
}
public static GGrassPrototypeGroup Create(DetailPrototype[] detailPrototypes)
{
GGrassPrototypeGroup group = CreateInstance<GGrassPrototypeGroup>();
for (int i = 0; i < detailPrototypes.Length; ++i)
{
group.Prototypes.Add((GGrassPrototype)detailPrototypes[i]);
}
return group;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 14882406f79bbd342b57fadf27f4c741
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 7bea79d99ea5d054280a13d815aafb36, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
#if GRIFFIN
namespace Pinwheel.Griffin
{
public enum GGrassShape
{
Quad, Cross, TriCross, Clump, DetailObject, CustomMesh
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 07499afc656f4094d9d2d93c0dee110d
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,133 @@
#if GRIFFIN
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
namespace Pinwheel.Griffin
{
public class GMask : ScriptableObject
{
public const string MASK_MAP_NAME = "Mask Map";
[SerializeField]
private GTerrainData terrainData;
public GTerrainData TerrainData
{
get
{
return terrainData;
}
internal set
{
terrainData = value;
}
}
[SerializeField]
private int maskMapResolution;
public int MaskMapResolution
{
get
{
return maskMapResolution;
}
set
{
int oldValue = maskMapResolution;
maskMapResolution = Mathf.Clamp(Mathf.ClosestPowerOfTwo(value), GCommon.TEXTURE_SIZE_MIN, GCommon.TEXTURE_SIZE_MAX);
if (oldValue != maskMapResolution)
{
ResampleMaskMap();
}
}
}
[SerializeField]
private Texture2D maskMap;
public Texture2D MaskMap
{
get
{
if (maskMap == null)
{
maskMap = GCommon.CreateTexture(MaskMapResolution, Color.clear, TextureFormat.RGBA32);
maskMap.filterMode = FilterMode.Bilinear;
maskMap.wrapMode = TextureWrapMode.Clamp;
maskMap.name = MASK_MAP_NAME;
}
GCommon.TryAddObjectToAsset(maskMap, TerrainData);
return maskMap;
}
}
public Texture2D MaskMapOrDefault
{
get
{
if (maskMap == null)
{
return GRuntimeSettings.Instance.defaultTextures.blackTexture;
}
else
{
return maskMap;
}
}
}
public void Reset()
{
name = "Mask";
MaskMapResolution = GRuntimeSettings.Instance.maskDefault.maskMapResolution;
}
public void ResetFull()
{
Reset();
if (maskMap!=null)
{
GUtilities.DestroyObject(maskMap);
}
}
public void CopyTo(GMask des)
{
des.MaskMapResolution = MaskMapResolution;
}
private void ResampleMaskMap()
{
if (maskMap == null)
return;
Texture2D tmp = new Texture2D(MaskMapResolution, MaskMapResolution, TextureFormat.RGBA32, false);
RenderTexture rt = new RenderTexture(MaskMapResolution, MaskMapResolution, 32, RenderTextureFormat.ARGB32);
GCommon.CopyToRT(maskMap, rt);
GCommon.CopyFromRT(tmp, rt);
rt.Release();
Object.DestroyImmediate(rt);
tmp.name = maskMap.name;
tmp.filterMode = maskMap.filterMode;
tmp.wrapMode = maskMap.wrapMode;
Object.DestroyImmediate(maskMap, true);
maskMap = tmp;
GCommon.TryAddObjectToAsset(maskMap, TerrainData);
}
public float GetMaskMapMemStats()
{
if (maskMap == null)
return 0;
return maskMap.width * maskMap.height * 4;
}
public void RemoveMaskMap()
{
if (maskMap != null)
{
GUtilities.DestroyObject(maskMap);
}
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: aba2bd1d74124a54d8737ba971cd7633
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,51 @@
#if GRIFFIN
using System.Collections.Generic;
using UnityEngine;
namespace Pinwheel.Griffin
{
[CreateAssetMenu(fileName = "Prefab Prototype Group", menuName = "Polaris/Prefab Prototype Group")]
public class GPrefabPrototypeGroup : ScriptableObject
{
[SerializeField]
private List<GameObject> prototypes;
public List<GameObject> Prototypes
{
get
{
if (prototypes == null)
prototypes = new List<GameObject>();
return prototypes;
}
set
{
prototypes = value;
}
}
#if UNITY_EDITOR
public List<string> editor_PrefabAssetPaths;
public List<string> Editor_PrefabAssetPaths
{
get
{
if (editor_PrefabAssetPaths == null)
{
editor_PrefabAssetPaths = new List<string>();
}
GUtilities.EnsureLengthSufficient(editor_PrefabAssetPaths, prototypes.Count);
return editor_PrefabAssetPaths;
}
set
{
editor_PrefabAssetPaths = value;
}
}
#endif
[SerializeField]
private bool isSampleAsset;
public bool IsSampleAsset => isSampleAsset;
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: c7b712840779f4647baae93e0b9355d2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 5f9926ffcb356ea4c9d4d0d0be344dbb, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,191 @@
#if GRIFFIN
using UnityEngine;
using UnityEngine.Serialization;
namespace Pinwheel.Griffin
{
public class GRendering : ScriptableObject
{
[SerializeField]
private GTerrainData terrainData;
public GTerrainData TerrainData
{
get
{
return terrainData;
}
internal set
{
terrainData = value;
}
}
[SerializeField]
private bool castShadow;
public bool CastShadow
{
get
{
return castShadow;
}
set
{
castShadow = value;
}
}
[SerializeField]
private bool receiveShadow;
public bool ReceiveShadow
{
get
{
return receiveShadow;
}
set
{
receiveShadow = value;
}
}
[FormerlySerializedAs("drawFoliage")]
[SerializeField]
private bool drawTrees;
public bool DrawTrees
{
get
{
return drawTrees;
}
set
{
drawTrees = value;
}
}
[SerializeField]
private bool drawGrasses = true;
public bool DrawGrasses
{
get
{
return drawGrasses;
}
set
{
drawGrasses = value;
}
}
[SerializeField]
private bool enableInstancing;
public bool EnableInstancing
{
get
{
if (!SystemInfo.supportsInstancing)
enableInstancing = false;
return enableInstancing;
}
set
{
if (SystemInfo.supportsInstancing)
{
enableInstancing = value;
}
else
{
enableInstancing = false;
}
}
}
[SerializeField]
private float billboardStart;
public float BillboardStart
{
get
{
return billboardStart;
}
set
{
billboardStart = Mathf.Clamp(value, 0, GCommon.MAX_TREE_DISTANCE);
}
}
[SerializeField]
private float treeDistance;
public float TreeDistance
{
get
{
return treeDistance;
}
set
{
treeDistance = Mathf.Clamp(value, 0, GCommon.MAX_TREE_DISTANCE);
}
}
[SerializeField]
private float grassDistance;
public float GrassDistance
{
get
{
return grassDistance;
}
set
{
grassDistance = Mathf.Clamp(value, 0, GCommon.MAX_GRASS_DISTANCE);
}
}
[SerializeField]
private float grassFadeStart;
public float GrassFadeStart
{
get
{
return grassFadeStart;
}
set
{
grassFadeStart = Mathf.Clamp01(value);
}
}
public void Reset()
{
name = "Rendering";
CastShadow = GRuntimeSettings.Instance.renderingDefault.terrainCastShadow;
ReceiveShadow = GRuntimeSettings.Instance.renderingDefault.terrainReceiveShadow;
DrawTrees = GRuntimeSettings.Instance.renderingDefault.drawTrees;
DrawGrasses = GRuntimeSettings.Instance.renderingDefault.drawGrasses;
EnableInstancing = GRuntimeSettings.Instance.renderingDefault.enableInstancing;
BillboardStart = GRuntimeSettings.Instance.renderingDefault.billboardStart;
TreeDistance = GRuntimeSettings.Instance.renderingDefault.treeDistance;
GrassDistance = GRuntimeSettings.Instance.renderingDefault.grassDistance;
GrassFadeStart = GRuntimeSettings.Instance.renderingDefault.grassFadeStart;
}
public void ResetFull()
{
Reset();
}
public void CopyTo(GRendering des)
{
des.CastShadow = CastShadow;
des.ReceiveShadow = ReceiveShadow;
des.DrawTrees = DrawTrees;
des.EnableInstancing = EnableInstancing;
des.BillboardStart = BillboardStart;
des.TreeDistance = TreeDistance;
des.GrassDistance = GrassDistance;
des.GrassFadeStart = GrassFadeStart;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: b6a04edb346a8b34c84035bf9a24b795
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,20 @@
fileFormatVersion: 2
guid: 2a1a3589e24589e4fb6840b44d1b21c5
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences:
- terrainData: {instanceID: 0}
- customMaterial: {instanceID: 0}
- albedoMap: {instanceID: 0}
- metallicMap: {instanceID: 0}
- colorByHeightMap: {instanceID: 0}
- colorByNormalMap: {instanceID: 0}
- colorBlendMap: {instanceID: 0}
- splats: {fileID: 11400000, guid: a3cfde07cd0a9f4488f10294d27e360e, type: 2}
- msTextureArrayConfig: {instanceID: 0}
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,198 @@
#if GRIFFIN
using UnityEngine;
namespace Pinwheel.Griffin
{
[System.Serializable]
public class GSplatPrototype
{
[SerializeField]
private Texture2D texture;
public Texture2D Texture
{
get
{
return texture;
}
set
{
texture = value;
}
}
[SerializeField]
private Texture2D normalMap;
public Texture2D NormalMap
{
get
{
return normalMap;
}
set
{
normalMap = value;
}
}
[SerializeField]
private Vector2 tileSize = Vector2.one;
public Vector2 TileSize
{
get
{
return tileSize;
}
set
{
tileSize = value;
}
}
[SerializeField]
private Vector2 tileOffset = Vector2.zero;
public Vector2 TileOffset
{
get
{
return tileOffset;
}
set
{
tileOffset = value;
}
}
[SerializeField]
private float metallic;
public float Metallic
{
get
{
return metallic;
}
set
{
metallic = Mathf.Clamp01(value);
}
}
[SerializeField]
private float smoothness;
public float Smoothness
{
get
{
return smoothness;
}
set
{
smoothness = Mathf.Clamp01(value);
}
}
public bool Equals(SplatPrototype layer)
{
return
texture == layer.texture &&
normalMap == layer.normalMap &&
tileSize == layer.tileSize &&
tileOffset == layer.tileOffset &&
metallic == layer.metallic &&
smoothness == layer.smoothness;
}
public void CopyTo(SplatPrototype layer)
{
layer.texture = Texture;
layer.normalMap = NormalMap;
layer.tileSize = TileSize;
layer.tileOffset = TileOffset;
layer.metallic = Metallic;
layer.smoothness = Smoothness;
}
public static explicit operator GSplatPrototype(SplatPrototype layer)
{
GSplatPrototype proto = new GSplatPrototype();
proto.Texture = layer.texture;
proto.NormalMap = layer.normalMap;
proto.TileSize = layer.tileSize;
proto.TileOffset = layer.tileOffset;
proto.Metallic = layer.metallic;
proto.Smoothness = layer.smoothness;
return proto;
}
public static explicit operator SplatPrototype(GSplatPrototype proto)
{
SplatPrototype layer = new SplatPrototype();
layer.texture = proto.Texture;
layer.normalMap = proto.NormalMap;
layer.tileSize = proto.TileSize;
layer.tileOffset = proto.TileOffset;
layer.metallic = proto.Metallic;
layer.smoothness = proto.Smoothness;
return layer;
}
#if !UNITY_2018_1 && !UNITY_2018_2
public bool Equals(TerrainLayer layer)
{
return
texture == layer.diffuseTexture &&
normalMap == layer.normalMapTexture &&
tileSize == layer.tileSize &&
tileOffset == layer.tileOffset &&
metallic == layer.metallic &&
smoothness == layer.smoothness;
}
public void CopyTo(TerrainLayer layer)
{
layer.diffuseTexture = Texture;
layer.normalMapTexture = NormalMap;
layer.tileSize = TileSize;
layer.tileOffset = TileOffset;
layer.metallic = Metallic;
layer.smoothness = Smoothness;
}
public static explicit operator GSplatPrototype(TerrainLayer layer)
{
GSplatPrototype proto = new GSplatPrototype();
proto.Texture = layer.diffuseTexture;
proto.NormalMap = layer.normalMapTexture;
proto.TileSize = layer.tileSize;
proto.TileOffset = layer.tileOffset;
proto.Metallic = layer.metallic;
proto.Smoothness = layer.smoothness;
return proto;
}
public static explicit operator TerrainLayer(GSplatPrototype proto)
{
TerrainLayer layer = new TerrainLayer();
layer.diffuseTexture = proto.Texture;
layer.normalMapTexture = proto.NormalMap;
layer.tileSize = proto.TileSize;
layer.tileOffset = proto.TileOffset;
layer.metallic = proto.Metallic;
layer.smoothness = proto.Smoothness;
return layer;
}
#endif
#if POLARIS
public static explicit operator GSplatPrototype(Pinwheel.Polaris.LPTSplatInfo layer)
{
GSplatPrototype proto = new GSplatPrototype();
proto.Texture = layer.Texture;
proto.NormalMap = layer.NormalMap;
proto.TileSize = Vector2.one;
proto.TileOffset = Vector2.zero;
return proto;
}
#endif
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: edc6c65ad8914524f857ca26dba396e4
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,81 @@
#if GRIFFIN
using System.Collections.Generic;
using UnityEngine;
namespace Pinwheel.Griffin
{
[CreateAssetMenu(fileName = "Splat Prototype Group", menuName = "Polaris/Splat Prototype Group")]
public class GSplatPrototypeGroup : ScriptableObject
{
[SerializeField]
private List<GSplatPrototype> prototypes;
public List<GSplatPrototype> Prototypes
{
get
{
if (prototypes == null)
{
prototypes = new List<GSplatPrototype>();
}
return prototypes;
}
set
{
prototypes = value;
}
}
[SerializeField]
private bool isSampleAsset;
public bool IsSampleAsset => isSampleAsset;
public bool Equals(SplatPrototype[] layers)
{
if (Prototypes.Count != layers.Length)
return false;
for (int i = 0; i < layers.Length; ++i)
{
if (!Prototypes[i].Equals(layers[i]))
return false;
}
return true;
}
public static GSplatPrototypeGroup Create(SplatPrototype[] layers)
{
GSplatPrototypeGroup group = CreateInstance<GSplatPrototypeGroup>();
for (int i = 0; i < layers.Length; ++i)
{
group.Prototypes.Add((GSplatPrototype)layers[i]);
}
return group;
}
#if !UNITY_2018_1 && !UNITY_2018_2
public bool Equals(TerrainLayer[] layers)
{
if (Prototypes.Count != layers.Length)
return false;
for (int i = 0; i < layers.Length; ++i)
{
if (!Prototypes[i].Equals(layers[i]))
return false;
}
return true;
}
public static GSplatPrototypeGroup Create(TerrainLayer[] layers)
{
GSplatPrototypeGroup group = CreateInstance<GSplatPrototypeGroup>();
for (int i = 0; i < layers.Length; ++i)
{
group.Prototypes.Add((GSplatPrototype)layers[i]);
}
return group;
}
#endif
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 8838f9e3fa4281f48a9a64c787c84798
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: b6b0facc21280084a9353d66d8faa793, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,264 @@
#if GRIFFIN
using UnityEngine;
using UnityEngine.Serialization;
#if UNITY_EDITOR
using UnityEditor;
#endif
namespace Pinwheel.Griffin
{
[CreateAssetMenu(fileName = "Terrain Data", menuName = "Polaris/Terrain Data")]
public class GTerrainData : ScriptableObject
{
public delegate void GlobalDirtyHandler(GTerrainData data, DirtyFlags flag);
public static event GlobalDirtyHandler GlobalDirty;
public delegate void DirtyHandler(DirtyFlags flag);
public event DirtyHandler Dirty;
internal delegate void GrassPatchChangedHandler(int index);
internal event GrassPatchChangedHandler GrassPatchChanged;
internal delegate void GrassPatchGridSizeChangedHandler();
internal event GrassPatchGridSizeChangedHandler GrassPatchGridSizeChanged;
internal delegate void TreeChangedHandler();
internal event TreeChangedHandler TreeChanged;
internal delegate void GrassPrototypeGroupChangedHandler();
internal event GrassPrototypeGroupChangedHandler GrassPrototypeGroupChanged;
[System.Flags]
public enum DirtyFlags : byte
{
None = 0,
Geometry = 1,
GeometryTimeSliced = 2,
Rendering = 4,
Shading = 8,
Foliage = 16,
Mask = 32,
All = byte.MaxValue
}
[SerializeField]
private string id;
public string Id
{
get
{
return id;
}
internal set
{
id = value;
}
}
[SerializeField]
private GGeometry geometry;
public GGeometry Geometry
{
get
{
if (geometry == null)
{
geometry = ScriptableObject.CreateInstance<GGeometry>();
geometry.TerrainData = this;
//geometry.ResetFull();
}
GCommon.TryAddObjectToAsset(geometry, this);
geometry.TerrainData = this;
return geometry;
}
}
[SerializeField]
private GShading shading;
public GShading Shading
{
get
{
if (shading == null)
{
shading = ScriptableObject.CreateInstance<GShading>();
shading.TerrainData = this;
//shading.ResetFull();
}
GCommon.TryAddObjectToAsset(shading, this);
shading.TerrainData = this;
return shading;
}
}
[SerializeField]
private GRendering rendering;
public GRendering Rendering
{
get
{
if (rendering == null)
{
rendering = ScriptableObject.CreateInstance<GRendering>();
rendering.TerrainData = this;
//rendering.ResetFull();
}
GCommon.TryAddObjectToAsset(rendering, this);
rendering.TerrainData = this;
return rendering;
}
}
[SerializeField]
private GFoliage foliage;
public GFoliage Foliage
{
get
{
if (foliage == null)
{
foliage = ScriptableObject.CreateInstance<GFoliage>();
foliage.TerrainData = this;
foliage.ResetFull();
}
GCommon.TryAddObjectToAsset(foliage, this);
foliage.TerrainData = this;
return foliage;
}
}
[SerializeField]
private GMask mask;
public GMask Mask
{
get
{
if (mask == null)
{
mask = ScriptableObject.CreateInstance<GMask>();
mask.TerrainData = this;
//mask.ResetFull();
}
GCommon.TryAddObjectToAsset(mask, this);
mask.TerrainData = this;
return mask;
}
}
[SerializeField]
[FormerlySerializedAs("generatedData")]
private GTerrainGeneratedData geometryData;
public GTerrainGeneratedData GeometryData
{
get
{
if (Geometry.StorageMode == GGeometry.GStorageMode.SaveToAsset)
{
if (geometryData == null)
{
geometryData = GCommon.GetTerrainGeneratedDataAsset(this, "GeneratedGeometry");
}
geometryData.TerrainData = this;
return geometryData;
}
else
{
return null;
}
}
set
{
geometryData = value;
}
}
public void Reset()
{
id = GCommon.GetUniqueID();
}
public void SetDirty(DirtyFlags flag)
{
#if UNITY_EDITOR
//EditorUtility.SetDirty(this);
if (flag == DirtyFlags.All || flag == DirtyFlags.Geometry)
{
EditorUtility.SetDirty(Geometry);
}
if (flag == DirtyFlags.All || flag == DirtyFlags.Shading)
{
EditorUtility.SetDirty(Shading);
}
if (flag == DirtyFlags.All || flag == DirtyFlags.Rendering)
{
EditorUtility.SetDirty(Rendering);
}
if (flag == DirtyFlags.All || flag == DirtyFlags.Foliage)
{
EditorUtility.SetDirty(Foliage);
}
#endif
Shading.UpdateMaterials();
if (Dirty != null)
{
Dirty(flag);
}
if (GlobalDirty != null)
{
GlobalDirty(this, flag);
}
}
public void CopyTo(GTerrainData des)
{
Geometry.CopyTo(des.Geometry);
Shading.CopyTo(des.Shading);
Rendering.CopyTo(des.Rendering);
Foliage.CopyTo(des.Foliage);
Mask.CopyTo(des.Mask);
}
internal void InvokeGrassChange(Vector2 gridIndex)
{
if (GrassPatchChanged != null)
{
int index = GUtilities.To1DIndex((int)gridIndex.x, (int)gridIndex.y, Foliage.PatchGridSize);
GrassPatchChanged.Invoke(index);
}
}
internal void InvokeGrassPatchGridSizeChange()
{
if (GrassPatchGridSizeChanged != null)
{
GrassPatchGridSizeChanged.Invoke();
}
}
internal void InvokeTreeChanged()
{
if (TreeChanged != null)
{
TreeChanged.Invoke();
}
}
internal void InvokeGrassPrototypeGroupChanged()
{
if (GrassPrototypeGroupChanged != null)
{
GrassPrototypeGroupChanged.Invoke();
}
}
public void CleanUp()
{
if (geometry != null && geometry.subDivisionMap != null)
{
GUtilities.DestroyObject(geometry.subDivisionMap);
}
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 9be8aeadd554b3c488c79555c2c46709
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 0a8bc049445e99c4494f4fa2af77c8bb, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,215 @@
#if GRIFFIN
using System.Collections.Generic;
using UnityEngine;
namespace Pinwheel.Griffin
{
//[CreateAssetMenu(menuName = "Griffin/Generated Data")]
[PreferBinarySerialization]
public class GTerrainGeneratedData : ScriptableObject, ISerializationCallbackReceiver
{
[SerializeField]
[HideInInspector]
private GTerrainData terrainData;
public GTerrainData TerrainData
{
get
{
return terrainData;
}
internal set
{
terrainData = value;
}
}
private Dictionary<string, Mesh> generatedMeshes;
private Dictionary<string, Mesh> GeneratedMeshes
{
get
{
if (generatedMeshes == null)
generatedMeshes = new Dictionary<string, Mesh>();
return generatedMeshes;
}
}
private Dictionary<Vector3Int, Mesh> meshes;
private Dictionary<Vector3Int, Mesh> Meshes
{
get
{
if (meshes == null)
{
meshes = new Dictionary<Vector3Int, Mesh>();
}
return meshes;
}
}
[SerializeField]
[HideInInspector]
private List<string> generatedMeshesKeys;
[SerializeField]
[HideInInspector]
private List<Mesh> generatedMeshesValues;
[SerializeField]
private List<Vector3Int> meshesKeys;
[SerializeField]
private List<Mesh> meshesValues;
[SerializeField]
private float serializeVersion = 0;
private const float SERIALIZE_VERSION_KEY_INT3 = 253;
private void Reset()
{
generatedMeshes = new Dictionary<string, Mesh>();
generatedMeshesKeys = new List<string>();
generatedMeshesValues = new List<Mesh>();
meshes = new Dictionary<Vector3Int, Mesh>();
meshesKeys = new List<Vector3Int>();
meshesValues = new List<Mesh>();
serializeVersion = GVersionInfo.Number;
}
private void OnEnable()
{
if (serializeVersion < SERIALIZE_VERSION_KEY_INT3)
{
UpgradeSerializeVersion();
}
}
public void OnBeforeSerialize()
{
//remain for backup
generatedMeshesKeys.Clear();
generatedMeshesValues.Clear();
foreach (string k in GeneratedMeshes.Keys)
{
if (GeneratedMeshes[k] != null)
{
generatedMeshesKeys.Add(k);
generatedMeshesValues.Add(GeneratedMeshes[k]);
}
}
meshesKeys.Clear();
meshesValues.Clear();
foreach (Vector3Int k in Meshes.Keys)
{
if (Meshes[k] != null)
{
meshesKeys.Add(k);
meshesValues.Add(Meshes[k]);
}
}
}
public void OnAfterDeserialize()
{
//remain for backup
if (generatedMeshesKeys != null && generatedMeshesValues != null)
{
GeneratedMeshes.Clear();
for (int i = 0; i < generatedMeshesKeys.Count; ++i)
{
string k = generatedMeshesKeys[i];
Mesh m = generatedMeshesValues[i];
if (!string.IsNullOrEmpty(k) && m != null)
{
GeneratedMeshes[k] = m;
}
}
}
if (meshesKeys != null && meshesValues != null)
{
Meshes.Clear();
for (int i = 0; i < meshesKeys.Count; ++i)
{
Vector3Int k = meshesKeys[i];
Mesh m = meshesValues[i];
Meshes[k] = m;
}
}
}
public void SetMesh(Vector3Int key, Mesh mesh)
{
if (Meshes.ContainsKey(key))
{
Mesh oldMesh = Meshes[key];
if (oldMesh != null)
{
GUtilities.DestroyObject(oldMesh);
}
Meshes.Remove(key);
}
GCommon.TryAddObjectToAsset(mesh, this);
Meshes.Add(key, mesh);
GCommon.SetDirty(this);
}
public Mesh GetMesh(Vector3Int key)
{
if (Meshes.ContainsKey(key))
return Meshes[key];
else
return null;
}
public void DeleteMesh(Vector3Int key)
{
if (Meshes.ContainsKey(key))
{
Mesh m = Meshes[key];
if (m != null)
{
GUtilities.DestroyObject(m);
}
Meshes.Remove(key);
GCommon.SetDirty(this);
}
}
public List<Vector3Int> GetKeys()
{
return new List<Vector3Int>(Meshes.Keys);
}
private void UpgradeSerializeVersion()
{
Meshes.Clear();
foreach (string k in GeneratedMeshes.Keys)
{
int subStrIndex = k.IndexOf('_');
if (subStrIndex < 0)
continue;
string indexString = k.Substring(subStrIndex);
string[] indices = indexString.Split(new string[] { "_" }, System.StringSplitOptions.RemoveEmptyEntries);
if (indices.Length != 3)
continue;
int x = 0;
int y = 0;
int z = 0;
int.TryParse(indices[0], out x);
int.TryParse(indices[1], out y);
int.TryParse(indices[2], out z);
Vector3Int newKey = new Vector3Int(x, y, z);
Mesh m = GeneratedMeshes[k];
Meshes.Add(newKey, m);
}
serializeVersion = GVersionInfo.Number;
#if UNITY_EDITOR
UnityEditor.EditorUtility.SetDirty(this);
#endif
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: ec3d40e1ff876504088fd473e4d47069
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: ce921e1c3c657de4987ff82d98c7ed88, type: 3}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,9 @@
#if GRIFFIN
namespace Pinwheel.Griffin
{
public enum GTerrainResourceFlag
{
HeightMap, AlbedoMap, MetallicMap, SplatControlMaps, MaskMap, TreeInstances, GrassInstances
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: f310329d58589fb4a92ad28f559e8602
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,104 @@
#if GRIFFIN
using UnityEngine;
namespace Pinwheel.Griffin
{
[System.Serializable]
public struct GTreeInstance
{
[SerializeField]
internal int prototypeIndex;
public int PrototypeIndex
{
get
{
return prototypeIndex;
}
set
{
prototypeIndex = value;
}
}
[SerializeField]
internal Vector3 position;
public Vector3 Position
{
get
{
return position;
}
set
{
position = value;
}
}
[SerializeField]
internal Quaternion rotation;
public Quaternion Rotation
{
get
{
return rotation;
}
set
{
rotation = value;
}
}
[SerializeField]
internal Vector3 scale;
public Vector3 Scale
{
get
{
return scale;
}
set
{
scale = value;
}
}
public static GTreeInstance Create(int prototypeIndex)
{
GTreeInstance tree = new GTreeInstance();
tree.PrototypeIndex = prototypeIndex;
tree.Position = Vector3.zero;
tree.Rotation = Quaternion.identity;
tree.Scale = Vector3.one;
return tree;
}
public static explicit operator GTreeInstance(TreeInstance t)
{
GTreeInstance tree = Create(t.prototypeIndex);
tree.Position = t.position;
tree.Rotation = Quaternion.Euler(0, t.rotation * Mathf.Rad2Deg, 0);
tree.Scale = new Vector3(t.widthScale, t.heightScale, t.widthScale);
return tree;
}
public static explicit operator TreeInstance(GTreeInstance t)
{
TreeInstance tree = new TreeInstance();
tree.prototypeIndex = t.PrototypeIndex;
tree.position = t.Position;
tree.widthScale = t.Scale.x;
tree.heightScale = t.Scale.y;
tree.color = Color.white;
return tree;
}
internal static int GetStructSize()
{
return sizeof(int) + sizeof(float) * 3 + sizeof(float) * 4 + sizeof(float) * 3;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cc0300a7925c93c46b6c519796ab65fa
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,357 @@
#if GRIFFIN
using UnityEngine;
using UnityEngine.Rendering;
using Pinwheel.Griffin.Physic;
namespace Pinwheel.Griffin
{
[System.Serializable]
public class GTreePrototype
{
[SerializeField]
internal GameObject prefab;
public GameObject Prefab
{
get
{
return prefab;
}
set
{
GameObject oldValue = prefab;
GameObject newValue = value;
prefab = newValue;
if (oldValue != newValue)
{
Refresh();
}
}
}
[HideInInspector]
[SerializeField]
internal Mesh sharedMesh;
public Mesh SharedMesh
{
get
{
return sharedMesh;
}
private set
{
sharedMesh = value;
}
}
[HideInInspector]
[SerializeField]
internal Material[] sharedMaterials;
public Material[] SharedMaterials
{
get
{
return sharedMaterials;
}
private set
{
sharedMaterials = value;
}
}
[HideInInspector]
[SerializeField]
internal ShadowCastingMode shadowCastingMode;
public ShadowCastingMode ShadowCastingMode
{
get
{
return shadowCastingMode;
}
set
{
shadowCastingMode = value;
}
}
[HideInInspector]
[SerializeField]
internal bool receiveShadow;
public bool ReceiveShadow
{
get
{
return receiveShadow;
}
set
{
receiveShadow = value;
}
}
[HideInInspector]
[SerializeField]
internal ShadowCastingMode billboardShadowCastingMode;
public ShadowCastingMode BillboardShadowCastingMode
{
get
{
return billboardShadowCastingMode;
}
set
{
billboardShadowCastingMode = value;
}
}
[HideInInspector]
[SerializeField]
internal bool billboardReceiveShadow;
public bool BillboardReceiveShadow
{
get
{
return billboardReceiveShadow;
}
set
{
billboardReceiveShadow = value;
}
}
[SerializeField]
internal int layer;
public int Layer
{
get
{
return layer;
}
set
{
layer = value;
}
}
[SerializeField]
private bool keepPrefabLayer;
public bool KeepPrefabLayer
{
get
{
return keepPrefabLayer;
}
set
{
keepPrefabLayer = value;
}
}
[SerializeField]
internal BillboardAsset billboard;
public BillboardAsset Billboard
{
get
{
return billboard;
}
set
{
billboard = value;
}
}
[SerializeField]
internal bool hasCollider;
public bool HasCollider
{
get
{
return hasCollider;
}
set
{
hasCollider = value;
}
}
[SerializeField]
internal GTreeColliderInfo colliderInfo;
public GTreeColliderInfo ColliderInfo
{
get
{
return colliderInfo;
}
set
{
colliderInfo = value;
}
}
[SerializeField]
private float pivotOffset;
public float PivotOffset
{
get
{
return pivotOffset;
}
set
{
pivotOffset = Mathf.Clamp(value, -1, 1);
}
}
[SerializeField]
private Quaternion baseRotation = Quaternion.identity;
public Quaternion BaseRotation
{
get
{
if (baseRotation.x == 0 &&
baseRotation.y == 0 &&
baseRotation.z == 0 &&
baseRotation.w == 0)
{
baseRotation = Quaternion.identity;
}
return baseRotation;
}
set
{
baseRotation = value;
if (baseRotation.x == 0 &&
baseRotation.y == 0 &&
baseRotation.z == 0 &&
baseRotation.w == 0)
{
baseRotation = Quaternion.identity;
}
}
}
[SerializeField]
private Vector3 baseScale = Vector3.one;
public Vector3 BaseScale
{
get
{
return baseScale;
}
set
{
baseScale = value;
}
}
#if UNITY_EDITOR
[SerializeField]
private string editor_PrefabAssetPath;
public string Editor_PrefabAssetPath
{
get
{
return editor_PrefabAssetPath;
}
set
{
editor_PrefabAssetPath = value;
}
}
#endif
public bool IsValid
{
get
{
return Prefab != null && SharedMesh != null && SharedMaterials != null;
}
}
public static GTreePrototype Create(GameObject g)
{
GTreePrototype prototype = new GTreePrototype();
prototype.Prefab = g;
prototype.PivotOffset = 0;
prototype.BaseRotation = Quaternion.identity;
prototype.BaseScale = Vector3.one;
return prototype;
}
public void Refresh()
{
if (Prefab == null)
{
SharedMesh = null;
SharedMaterials = null;
ShadowCastingMode = ShadowCastingMode.Off;
ReceiveShadow = false;
Layer = 0;
}
else
{
MeshFilter mf = Prefab.GetComponentInChildren<MeshFilter>();
if (mf != null)
{
SharedMesh = mf.sharedMesh;
}
MeshRenderer mr = Prefab.GetComponentInChildren<MeshRenderer>();
if (mr != null)
{
SharedMaterials = mr.sharedMaterials;
ShadowCastingMode = mr.shadowCastingMode;
ReceiveShadow = mr.receiveShadows;
}
CapsuleCollider col = Prefab.GetComponentInChildren<CapsuleCollider>();
hasCollider = col != null;
if (col != null)
{
ColliderInfo = new GTreeColliderInfo(col);
}
if (KeepPrefabLayer)
{
Layer = Prefab.layer;
}
}
if (BaseScale == Vector3.zero)
BaseScale = Vector3.one;
}
public static explicit operator GTreePrototype(TreePrototype p)
{
return Create(p.prefab);
}
public static explicit operator TreePrototype(GTreePrototype p)
{
TreePrototype prototype = new TreePrototype();
prototype.prefab = p.Prefab;
return prototype;
}
public bool Equals(TreePrototype treePrototype)
{
return Prefab == treePrototype.prefab;
}
public BoundingSphere GetBoundingSphere()
{
if (SharedMesh == null)
{
return new BoundingSphere(Vector3.zero, 0);
}
else
{
Bounds b = SharedMesh.bounds;
Vector3 pos = b.center;
float radius = Vector3.Distance(b.max, b.center);
return new BoundingSphere(pos, radius);
}
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: cacd406cda25dec46a2c4e5e26751fef
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:

View File

@@ -0,0 +1,54 @@
#if GRIFFIN
using System.Collections.Generic;
using UnityEngine;
namespace Pinwheel.Griffin
{
[CreateAssetMenu(fileName = "Tree Prototype Group", menuName = "Polaris/Tree Prototype Group")]
public class GTreePrototypeGroup : ScriptableObject
{
[SerializeField]
private List<GTreePrototype> prototypes;
public List<GTreePrototype> Prototypes
{
get
{
if (prototypes == null)
prototypes = new List<GTreePrototype>();
return prototypes;
}
set
{
prototypes = value;
}
}
[SerializeField]
private bool isSampleAsset;
public bool IsSampleAsset => isSampleAsset;
public bool Equals(TreePrototype[] treePrototypes)
{
if (Prototypes.Count != treePrototypes.Length)
return false;
for (int i = 0; i < Prototypes.Count; ++i)
{
if (!Prototypes[i].Equals(treePrototypes[i]))
return false;
}
return true;
}
public static GTreePrototypeGroup Create(TreePrototype[] treePrototypes)
{
GTreePrototypeGroup group = CreateInstance<GTreePrototypeGroup>();
for (int i = 0; i < treePrototypes.Length; ++i)
{
group.Prototypes.Add((GTreePrototype)treePrototypes[i]);
}
return group;
}
}
}
#endif

View File

@@ -0,0 +1,11 @@
fileFormatVersion: 2
guid: 4e8fda743b539a043b220ae6e99779c2
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {fileID: 2800000, guid: 46329a0916a135c4d85ecbb651424ba0, type: 3}
userData:
assetBundleName:
assetBundleVariant: