1
This commit is contained in:
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 400f8297c7702214bbf272e603499de0
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -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:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 904d00621ec49474a970b363de76e74d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: da65cc640ca49214eaaf69531b38de16
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a8351d78df2822943bfaa51a9d02196d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: fdd540a19ffbded44b9fb5512ac97475
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96bda82f18917ee469871bc317ae9b8d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -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:
|
@@ -0,0 +1,9 @@
|
||||
#if GRIFFIN
|
||||
namespace Pinwheel.Griffin
|
||||
{
|
||||
public enum GGrassShape
|
||||
{
|
||||
Quad, Cross, TriCross, Clump, DetailObject, CustomMesh
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 07499afc656f4094d9d2d93c0dee110d
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: aba2bd1d74124a54d8737ba971cd7633
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -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:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b6a04edb346a8b34c84035bf9a24b795
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
File diff suppressed because it is too large
Load Diff
@@ -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:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: edc6c65ad8914524f857ca26dba396e4
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -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:
|
@@ -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
|
@@ -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:
|
@@ -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
|
@@ -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:
|
@@ -0,0 +1,9 @@
|
||||
#if GRIFFIN
|
||||
namespace Pinwheel.Griffin
|
||||
{
|
||||
public enum GTerrainResourceFlag
|
||||
{
|
||||
HeightMap, AlbedoMap, MetallicMap, SplatControlMaps, MaskMap, TreeInstances, GrassInstances
|
||||
}
|
||||
}
|
||||
#endif
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f310329d58589fb4a92ad28f559e8602
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cc0300a7925c93c46b6c519796ab65fa
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: cacd406cda25dec46a2c4e5e26751fef
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
@@ -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
|
@@ -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:
|
Reference in New Issue
Block a user