Add Unity3D projects

This commit is contained in:
2024-03-09 19:25:59 +00:00
parent 1c71f24fab
commit 829289c881
4626 changed files with 441247 additions and 0 deletions

View File

@ -0,0 +1,106 @@
#region "Imports"
using UnityEngine;
using System.Collections.Generic;
#endregion
namespace RoadArchitect
{
[ExecuteInEditMode]
public class RoadTerrain : MonoBehaviour
{
#region "Vars"
[SerializeField]
[HideInInspector]
private int uID = -1;
public int UID { get { return uID; } }
[HideInInspector]
public Terrain terrain;
//Splat map:
public int splatResoWidth = 1024;
public int splatResoHeight = 1024;
public Color splatBackground = new Color(0f, 0f, 0f, 1f);
public Color splatForeground = new Color(1f, 1f, 1f, 1f);
public float splatWidth = 30f;
public bool isSplatSkipBridges = false;
public bool isSplatSkipTunnels = false;
public bool isSplatSingleRoad = false;
public int splatSingleChoiceIndex = 0;
public string roadSingleChoiceUID = "";
#endregion
private void OnEnable()
{
CheckID();
if (!terrain)
{
terrain = transform.gameObject.GetComponent<Terrain>();
}
}
/// <summary> Check for unique id and assign terrain </summary>
public void CheckID()
{
if (uID < 0)
{
uID = GetNewID();
}
if (!terrain)
{
terrain = transform.gameObject.GetComponent<Terrain>();
}
}
/// <summary> Return new id preventing terrain id duplication </summary>
private int GetNewID()
{
Object[] allTerrainObjs = GameObject.FindObjectsOfType<RoadTerrain>();
List<int> allIDS = new List<int>(allTerrainObjs.Length);
foreach (RoadTerrain Terrain in allTerrainObjs)
{
if (Terrain.UID > 0)
{
allIDS.Add(Terrain.UID);
}
}
bool isNotDone = true;
int spamChecker = 0;
int spamCheckerMax = allIDS.Count + 64;
int random;
while (isNotDone)
{
if (spamChecker > spamCheckerMax)
{
Debug.LogError("Failed to generate terrainID");
break;
}
random = Random.Range(1, 2000000000);
if (!allIDS.Contains(random))
{
isNotDone = false;
return random;
}
spamChecker += 1;
}
return -1;
}
private void Start()
{
CheckID();
if (!terrain)
{
terrain = transform.gameObject.GetComponent<Terrain>();
}
}
}
}

View File

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 81fe195562332d04ead2688a86c7325b
MonoImporter:
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:

View File

@ -0,0 +1,645 @@
using System.Collections.Generic;
using UnityEngine;
namespace RoadArchitect
{
public static class Terraforming
{
public class TempTerrainData
{
public int HM;
public int HMHeight;
public float[,] heights;
public bool[,] tHeights;
public float HMRatio;
public float MetersPerHM = 0f;
//Heights:
public ushort[] cX;
public ushort[] cY;
public float[] cH;
public float[] oldH;
public int Count = 0;
public int TerrainMaxIndex;
//Details:
public int DetailLayersCount;
public List<ushort> MainDetailsX;
public List<ushort> MainDetailsY;
public List<List<ushort>> DetailsX;
public List<List<ushort>> DetailsY;
public List<List<ushort>> OldDetailsValue;
//public Dictionary<int,int[,]> DetailValues;
public int[] detailsCount;
public float DetailToHeightRatio;
//public Dictionary<int,bool[,]> DetailHasProcessed;
public HashSet<int> DetailHasProcessed;
//public List<List<bool>> OldDetailsValue;
public int DetailMaxIndex;
public HashSet<int> DetailLayersSkip;
//Trees
public List<TreeInstance> TreesCurrent;
public List<TreeInstance> TreesOld;
public int treesCount;
public int TreeSize;
public Vector3 TerrainSize;
public Vector3 TerrainPos;
public int uID;
public void Nullify()
{
heights = null;
tHeights = null;
cX = null;
cY = null;
cH = null;
oldH = null;
//DetailsX = null;
//DetailsY = null;
//DetailValues = null;
OldDetailsValue = null;
//DetailsI = null;
TreesCurrent = null;
TreesOld = null;
}
}
/// <summary> Checks all terrains and adds RoadTerrain if necessary </summary>
private static void CheckAllTerrains()
{
Object[] allTerrains = GameObject.FindObjectsOfType<Terrain>();
RoadTerrain TID;
GameObject terrainObj;
foreach (Terrain terrain in allTerrains)
{
terrainObj = terrain.transform.gameObject;
TID = terrainObj.GetComponent<RoadTerrain>();
if (TID == null)
{
TID = terrainObj.AddComponent<RoadTerrain>();
}
TID.CheckID();
}
}
/// <summary> Checks if every Terrain uses a RoadTerrain script and set it to 0 on y </summary>
public static void CheckAllTerrainsHeight0()
{
CheckAllTerrains();
Object[] allTerrains = GameObject.FindObjectsOfType<Terrain>();
foreach (Terrain terrain in allTerrains)
{
if (!RootUtils.IsApproximately(terrain.transform.position.y, 0f, 0.0001f))
{
Vector3 tVect = terrain.transform.position;
tVect.y = 0f;
terrain.transform.position = tVect;
}
}
}
/// <summary> Stores terrain infos and starts terrain calculations </summary>
public static void ProcessRoadTerrainHook1(SplineC _spline, Road _road, bool _isMultithreaded = true)
{
ProcessRoadTerrainHook1Do(ref _spline, ref _road, _isMultithreaded);
}
private static void ProcessRoadTerrainHook1Do(ref SplineC _spline, ref Road _road, bool _isMultithreaded)
{
RootUtils.StartProfiling(_road, "ProcessRoadTerrainHook1");
//First lets make sure all terrains have a RoadTerrain script:
CheckAllTerrains();
//Reset the terrain:
RootUtils.StartProfiling(_road, "TerrainsReset");
TerrainsReset(_road);
RootUtils.EndProfiling(_road);
float heightDistance = _road.matchHeightsDistance;
//float treeDistance = _road.clearTreesDistance;
float detailDistance = _road.clearDetailsDistance;
Dictionary<Terrain, TempTerrainData> TempTerrainDict = new Dictionary<Terrain, TempTerrainData>();
//Populate dictionary:
Object[] allTerrains = GameObject.FindObjectsOfType<Terrain>();
RoadTerrain TID;
int aSize = 0;
int dSize = 0;
TempTerrainData TTD;
bool isContaining = false;
Construction2DRect tRect = null;
//Construction2DRect rRect = null;
foreach (Terrain terrain in allTerrains)
{
if (terrain.terrainData == null)
{
continue;
}
tRect = GetTerrainBounds(terrain);
isContaining = false;
//Debug.Log(terrain.transform.name + " bounds: " + tRect.ToStringRA());
//Debug.Log(" Road bounds: " + tSpline.RoadV0 + "," + tSpline.RoadV1 + "," + tSpline.RoadV2 + "," + tSpline.RoadV3);
// Check if the terrain overlaps with a part of the spline
if (isContaining != true && tRect.Contains(ref _spline.RoadV0))
{
isContaining = true;
}
else if (isContaining != true && tRect.Contains(ref _spline.RoadV1))
{
isContaining = true;
}
else if (isContaining != true && tRect.Contains(ref _spline.RoadV2))
{
isContaining = true;
}
else if (isContaining != true && tRect.Contains(ref _spline.RoadV3))
{
isContaining = true;
}
else
{
int nodeCount = _road.spline.GetNodeCount();
Vector2 tVect2D_321 = default(Vector2);
for (int index = 0; index < nodeCount; index++)
{
tVect2D_321 = new Vector2(_road.spline.nodes[index].pos.x, _road.spline.nodes[index].pos.z);
if (tRect.Contains(ref tVect2D_321))
{
isContaining = true;
break;
}
}
if (!isContaining)
{
float tDef = 5f / _spline.distance;
Vector2 x2D = default(Vector2);
Vector3 x3D = default(Vector3);
for (float index = 0f; index <= 1f; index += tDef)
{
x3D = _spline.GetSplineValue(index);
x2D = new Vector2(x3D.x, x3D.z);
if (tRect.Contains(ref x2D))
{
isContaining = true;
break;
}
}
}
}
//rRect = new RoadUtility.Construction2DRect(tSpline.RoadV0,tSpline.RoadV1,tSpline.RoadV2,tSpline.RoadV3);
if (isContaining && !TempTerrainDict.ContainsKey(terrain))
{
TTD = new TempTerrainData();
TTD.HM = terrain.terrainData.heightmapResolution;
TTD.HMHeight = terrain.terrainData.heightmapResolution;
TTD.heights = terrain.terrainData.GetHeights(0, 0, terrain.terrainData.heightmapResolution, terrain.terrainData.heightmapResolution);
TTD.HMRatio = TTD.HM / terrain.terrainData.size.x;
TTD.MetersPerHM = terrain.terrainData.size.x / terrain.terrainData.heightmapResolution;
float DetailRatio = terrain.terrainData.detailResolution / terrain.terrainData.size.x;
//Heights:
RootUtils.StartProfiling(_road, "Heights");
if (_road.isHeightModificationEnabled)
{
aSize = (int)_spline.distance * ((int)(heightDistance * 1.65f * TTD.HMRatio) + 2);
if (aSize > (terrain.terrainData.heightmapResolution * terrain.terrainData.heightmapResolution))
{
aSize = terrain.terrainData.heightmapResolution * terrain.terrainData.heightmapResolution;
}
TTD.cX = new ushort[aSize];
TTD.cY = new ushort[aSize];
TTD.oldH = new float[aSize];
TTD.cH = new float[aSize];
TTD.Count = 0;
TTD.TerrainMaxIndex = terrain.terrainData.heightmapResolution;
TTD.TerrainSize = terrain.terrainData.size;
TTD.TerrainPos = terrain.transform.position;
TTD.tHeights = new bool[terrain.terrainData.heightmapResolution, terrain.terrainData.heightmapResolution];
TID = terrain.transform.gameObject.GetComponent<RoadTerrain>();
if (TID != null)
{
TTD.uID = TID.UID;
TempTerrainDict.Add(terrain, TTD);
}
}
//Details:
RootUtils.EndStartProfiling(_road, "Details");
if (_road.isDetailModificationEnabled)
{
//TTD.DetailValues = new Dictionary<int, int[,]>();
TTD.DetailLayersCount = terrain.terrainData.detailPrototypes.Length;
//TTD.DetailHasProcessed = new Dictionary<int, bool[,]>();
TTD.DetailHasProcessed = new HashSet<int>();
TTD.MainDetailsX = new List<ushort>();
TTD.MainDetailsY = new List<ushort>();
TTD.detailsCount = new int[TTD.DetailLayersCount];
TTD.DetailToHeightRatio = (float)((float)terrain.terrainData.detailResolution) / ((float)terrain.terrainData.heightmapResolution);
TTD.DetailMaxIndex = terrain.terrainData.detailResolution;
TTD.DetailLayersSkip = new HashSet<int>();
// Get all of layer zero.
//int[] mMinMaxDetailEntryCount = new int[TTD.DetailLayersCount];
//RootUtils.StartProfiling(_road, "DetailValues");
//Vector3 bVect = default(Vector3);
//Vector2 bVect2D = default(Vector2);
//int DetailRes = tTerrain.terrainData.detailResolution;
//for(int i=0;i<TTD.DetailLayersCount;i++)
//{
// int[,] tInts = tTerrain.terrainData.GetDetailLayer(0,0,tTerrain.terrainData.detailWidth,tTerrain.terrainData.detailHeight,i);
// int Length1 = tInts.GetLength(0);
// int Length2 = tInts.GetLength(1);
// for (int y=0;y < Length1;y++)
// {
// for (int x=0;x < Length2;x++)
// {
// if(tInts[x,y] > 0)
// {
// bVect = new Vector3(((float)y/(float)DetailRes) * TTD.TerrainSize.x,0f,((float)x/(float)DetailRes) * TTD.TerrainSize.z);
// bVect = tTerrain.transform.TransformPoint(bVect);
// bVect2D = new Vector2(bVect.z,bVect.x);
// if(rRect.Contains(ref bVect2D))
// {
// mMinMaxDetailEntryCount[i] += 1;
// }
// }
// }
// }
// if(mMinMaxDetailEntryCount[i] < 1)
// {
// TTD.DetailLayersSkip.Add(i);
// tInts = null;
// }
// else
// {
// TTD.DetailValues.Add(i,tInts);
// TTD.DetailHasProcessed.Add(i,new bool[tTerrain.terrainData.detailWidth,tTerrain.terrainData.detailHeight]);
// }
// }
//RootUtils.EndProfiling(_road);
dSize = (int)_spline.distance * ((int)(detailDistance * 3f * DetailRatio) + 2);
if (dSize > (terrain.terrainData.detailResolution * terrain.terrainData.detailResolution))
{
dSize = terrain.terrainData.detailResolution * terrain.terrainData.detailResolution;
}
//TTD.DetailsX = new List<ushort[]>();
//TTD.DetailsY = new List<ushort[]>();
//TTD.OldDetailsValue = new List<ushort[]>();
TTD.DetailsX = new List<List<ushort>>();
TTD.DetailsY = new List<List<ushort>>();
TTD.OldDetailsValue = new List<List<ushort>>();
//TTD.DetailHasProcessed = new List<List<bool>>();
for (int index = 0; index < TTD.DetailLayersCount; index++)
{
//if(TTD.DetailLayersSkip.Contains(index))
//{
// TTD.DetailsX.Add(new ushort[0]);
// TTD.DetailsY.Add(new ushort[0]);
// TTD.OldDetailsValue.Add(new ushort[0]);
// continue;
//}
//int detailentrycount = (int)((float)mMinMaxDetailEntryCount[index] * 1.5f);
//int d_temp_Size = dSize;
//if(d_temp_Size > detailentrycount)
//{
// d_temp_Size = detailentrycount;
//}
//if(d_temp_Size < 1)
//{
// d_temp_Size = 1;
//}
//if(d_temp_Size > (tTerrain.terrainData.detailResolution * tTerrain.terrainData.detailResolution))
//{
// d_temp_Size = tTerrain.terrainData.detailResolution * tTerrain.terrainData.detailResolution;
//}
//
//TTD.DetailsX.Add(new ushort[d_temp_Size]);
//TTD.DetailsY.Add(new ushort[d_temp_Size]);
//TTD.OldDetailsValue.Add(new ushort[d_temp_Size]);
TTD.DetailsX.Add(new List<ushort>());
TTD.DetailsY.Add(new List<ushort>());
TTD.OldDetailsValue.Add(new List<ushort>());
}
//TTD.DetailsX = new ushort[TTD.DetailLayersCount,dSize];
//TTD.DetailsY = new ushort[TTD.DetailLayersCount,dSize];
//TTD.OldDetailsValue = new ushort[TTD.DetailLayersCount,dSize];
}
//Trees:
RootUtils.EndStartProfiling(_road, "Trees");
if (_road.isTreeModificationEnabled)
{
TTD.TreesCurrent = new List<TreeInstance>(terrain.terrainData.treeInstances);
TTD.TreeSize = TTD.TreesCurrent.Count;
TTD.treesCount = 0;
TTD.TreesOld = new List<TreeInstance>();
}
RootUtils.EndProfiling(_road);
}
}
//Figure out relevant TTD to spline:
List<TempTerrainData> EditorTTDList = new List<TempTerrainData>();
if (TempTerrainDict != null)
{
foreach (Terrain tTerrain in allTerrains)
{
if (TempTerrainDict.ContainsKey(tTerrain))
{
EditorTTDList.Add(TempTerrainDict[tTerrain]);
}
}
}
RootUtils.EndProfiling(_road);
//Start job now, for each relevant TTD:
_road.SetEditorTerrainCalcs(ref EditorTTDList);
if (_isMultithreaded)
{
Threading.TerrainCalcs terrainJob = new Threading.TerrainCalcs();
terrainJob.Setup(ref EditorTTDList, _spline, _road);
_road.TerrainCalcsJob = terrainJob;
terrainJob.Start();
}
else
{
Threading.TerrainCalcsStatic.RunMe(ref EditorTTDList, _spline, _road);
}
}
/// <summary> Returns an 2D rect of the terrain </summary>
public static Construction2DRect GetTerrainBounds(Terrain _terrain)
{
float terrainWidth = _terrain.terrainData.size.x;
float terrainLength = _terrain.terrainData.size.z;
//Vector3 tPos = tTerrain.transform.TransformPoint(tTerrain.transform.position);
Vector3 X0 = new Vector3(0f, 0f, 0f);
Vector3 X1 = new Vector3(terrainWidth, 0f, 0f);
Vector3 X2 = new Vector3(terrainWidth, 0f, terrainLength);
Vector3 X3 = new Vector3(0f, 0f, terrainLength);
X0 = _terrain.transform.TransformPoint(X0);
X1 = _terrain.transform.TransformPoint(X1);
X2 = _terrain.transform.TransformPoint(X2);
X3 = _terrain.transform.TransformPoint(X3);
Vector2 P0 = new Vector2(X0.x, X0.z);
Vector2 P1 = new Vector2(X1.x, X1.z);
Vector2 P2 = new Vector2(X2.x, X2.z);
Vector2 P3 = new Vector2(X3.x, X3.z);
//OLD CODE:
//Vector2 P0 = new Vector2(0f, 0f);
//Vector2 P1 = new Vector2(terrainWidth, 0f);
//Vector2 P2 = new Vector2(terrainWidth, terrainLength);
//Vector2 P3 = new Vector2(0f, terrainLength);
//P0 = tTerrain.transform.TransformPoint(P0);
//P1 = tTerrain.transform.TransformPoint(P1);
//P2 = tTerrain.transform.TransformPoint(P2);
//P3 = tTerrain.transform.TransformPoint(P3);
return new Construction2DRect(P0, P1, P2, P3, _terrain.transform.position.y);
}
/// <summary> Assign calculated values to terrains </summary>
public static void ProcessRoadTerrainHook2(SplineC _spline, ref List<TempTerrainData> _TTDList)
{
RootUtils.StartProfiling(_spline.road, "ProcessRoadTerrainHook2");
ProcessRoadTerrainHook2Do(ref _spline, ref _TTDList);
RootUtils.EndProfiling(_spline.road);
}
private static void ProcessRoadTerrainHook2Do(ref SplineC _spline, ref List<TempTerrainData> _TTDList)
{
if (!_spline.road.isTreeModificationEnabled && !_spline.road.isHeightModificationEnabled && !_spline.road.isDetailModificationEnabled)
{
//Exit if no mod taking place.
return;
}
Object[] TIDs = GameObject.FindObjectsOfType<RoadTerrain>();
Terrain terrain;
int[,] tDetails = null;
int IntBufferX = 0;
int IntBufferY = 0;
int tVal = 0;
foreach (TempTerrainData TTD in _TTDList)
{
foreach (RoadTerrain TID in TIDs)
{
if (TID.UID != TTD.uID)
{
continue;
}
terrain = TID.transform.gameObject.GetComponent<Terrain>();
if (terrain == null)
{
continue;
}
//Details:
if (_spline.road.isDetailModificationEnabled)
{
for (int index = 0; index < TTD.DetailLayersCount; index++)
{
//if(TTD.DetailLayersSkip.Contains(i) || TTD.DetailValues[i] == null)
//{
// continue;
//}
//if(TTD.DetailsI[i] > 0)
//{
// tTerrain.terrainData.SetDetailLayer(0, 0, i, TTD.DetailValues[i]);
//}
if (TTD.DetailLayersSkip.Contains(index) || TTD.MainDetailsX == null || TTD.MainDetailsX.Count < 1)
{
continue;
}
tDetails = terrain.terrainData.GetDetailLayer(0, 0, TTD.DetailMaxIndex, TTD.DetailMaxIndex, index);
int MaxCount = TTD.MainDetailsX.Count;
for (int j = 0; j < MaxCount; j++)
{
IntBufferX = TTD.MainDetailsX[j];
IntBufferY = TTD.MainDetailsY[j];
tVal = tDetails[IntBufferX, IntBufferY];
if (tVal > 0)
{
TTD.DetailsX[index].Add((ushort)IntBufferX);
TTD.DetailsY[index].Add((ushort)IntBufferY);
TTD.OldDetailsValue[index].Add((ushort)tVal);
tDetails[IntBufferX, IntBufferY] = 0;
}
}
TTD.detailsCount[index] = TTD.DetailsX[index].Count;
terrain.terrainData.SetDetailLayer(0, 0, index, tDetails);
tDetails = null;
TTD.DetailHasProcessed = null;
}
TTD.MainDetailsX = null;
TTD.MainDetailsY = null;
System.GC.Collect();
}
//Trees:
if (_spline.road.isTreeModificationEnabled && TTD.TreesCurrent != null && TTD.treesCount > 0)
{
terrain.terrainData.treeInstances = TTD.TreesCurrent.ToArray();
}
//Heights:
if (_spline.road.isHeightModificationEnabled && TTD.heights != null && TTD.Count > 0)
{
//Do heights last to trigger collisions and stuff properly:
terrain.terrainData.SetHeights(0, 0, TTD.heights);
}
}
}
}
public static void TerrainsReset(Road _road)
{
if (_road.TerrainHistory == null)
{
return;
}
if (_road.TerrainHistory.Count < 1)
{
return;
}
Object[] TIDs = GameObject.FindObjectsOfType<RoadTerrain>();
float[,] heights;
int[,] tDetails;
int ArrayCount;
foreach (TerrainHistoryMaker TH in _road.TerrainHistory)
{
Terrain terrain = null;
foreach (RoadTerrain TID in TIDs)
{
if (TID.UID == TH.terrainID)
{
terrain = TID.terrain;
}
}
if (!terrain)
{
continue;
}
if (TH.heightmapResolution != terrain.terrainData.heightmapResolution)
{
TH.Nullify();
continue;
}
//Heights:
if (TH.x1 != null)
{
heights = terrain.terrainData.GetHeights(0, 0, terrain.terrainData.heightmapResolution, terrain.terrainData.heightmapResolution);
ArrayCount = TH.Count;
for (int index = 0; index < ArrayCount; index++)
{
heights[TH.x1[index], TH.y1[index]] = TH.height[index];
}
terrain.terrainData.SetHeights(0, 0, heights);
}
//Details:
if (TH.detailsCount != null && TH.detailsX != null && TH.detailsY != null && TH.detailsOldValue != null)
{
int RealLayerCount = terrain.terrainData.detailPrototypes.Length;
int StartIndex = 0;
int EndIndex = 0;
for (int index = 0; index < TH.detailLayersCount; index++)
{
if (index >= RealLayerCount)
{
break;
}
if (TH.detailsX.Length <= index)
{
break;
}
if (TH.detailsY.Length <= index)
{
break;
}
if (TH.detailsX.Length < 1)
{
continue;
}
tDetails = terrain.terrainData.GetDetailLayer(0, 0, terrain.terrainData.detailWidth, terrain.terrainData.detailHeight, index);
ArrayCount = TH.detailsCount[index];
if (ArrayCount == 0)
{
continue;
}
EndIndex += ArrayCount;
for (int j = StartIndex; j < EndIndex; j++)
{
tDetails[TH.detailsX[j], TH.detailsY[j]] = TH.detailsOldValue[j];
}
StartIndex = EndIndex;
terrain.terrainData.SetDetailLayer(0, 0, index, tDetails);
tDetails = null;
}
}
//Trees:
TreeInstance[] xTress = TH.MakeTrees();
if (xTress != null)
{
ArrayCount = xTress.Length;
if (ArrayCount > 0 && TH.oldTrees != null)
{
int TerrainTreeCount = terrain.terrainData.treeInstances.Length;
TreeInstance[] tTrees = new TreeInstance[ArrayCount + TerrainTreeCount];
System.Array.Copy(terrain.terrainData.treeInstances, 0, tTrees, 0, TerrainTreeCount);
System.Array.Copy(xTress, 0, tTrees, TerrainTreeCount, ArrayCount);
terrain.terrainData.treeInstances = tTrees;
}
xTress = null;
}
}
System.GC.Collect();
}
}
}

View File

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

View File

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

View File

@ -0,0 +1,104 @@
using System.Collections.Generic;
namespace RoadArchitect.Threading
{
public class TerrainCalcs : ThreadedJob
{
private object handle = new object();
private List<Terraforming.TempTerrainData> TTDList;
private SplineC spline;
private Road road;
public void Setup(ref List<Terraforming.TempTerrainData> _TTDList, SplineC _tSpline, Road _tRoad)
{
TTDList = _TTDList;
spline = _tSpline;
road = _tRoad;
}
protected override void ThreadFunction()
{
float Step = (road.roadDefinition * 0.4f) / spline.distance;
if (Step > 2f)
{
Step = 2f;
}
if (Step < 1f)
{
Step = 1f;
}
//float tDistance = tRoad.RoadWidth()*2f;
//Vector3 tVect, POS;
foreach (Terraforming.TempTerrainData TTD in TTDList)
{
//float PrevHeight = 0f;
//float FinalMax = 1f;
//float StartMin = 0f;
//if(tSpline.bSpecialEndControlNode)
//{
// FinalMax = tSpline.mNodes[tSpline.GetNodeCount()-2].tTime;
//}
//if(tSpline.bSpecialStartControlNode)
//{
// StartMin = tSpline.mNodes[1].tTime;
//}
//if(tRoad.opt_MatchTerrain)
//{
try
{
TerraformingThreaded.DoRects(spline, TTD);
}
catch (System.Exception e)
{
lock (handle)
{
road.isEditorError = true;
road.exceptionError = e;
}
throw e;
}
//}
//else
//{
// for(float i=StartMin;i<=FinalMax;i+=Step)
// {
// if(tSpline.IsInBridgeTerrain(i))
// {
// float tFloat = tSpline.GetBridgeEnd(i);
// if(IsApproximately(tFloat,1f,0.00001f) || tFloat > 1f)
// {
// continue;
// }
// if(tFloat < 0f)
// {
// continue;
// }
// i = tFloat;
// }
// tSpline.GetSplineValue_Both(i,out tVect,out POS);
// PrevHeight = TerraformingThreaded.ProcessLineHeights(tSpline,ref tVect,ref POS,tDistance,TTD,PrevHeight);
// tSpline.HeightHistory.Add(new KeyValuePair<float,float>(i,PrevHeight*TTD.TerrainSize.y));
// }
//
// for(int i=0;i<TTD.cI;i++)
// {
// TTD.heights[TTD.cX[i],TTD.cY[i]] = TTD.cH[i];
// }
//}
}
spline.HeightHistory.Sort(CompareKeys);
IsDone = true;
}
private int CompareKeys(KeyValuePair<float, float> _a, KeyValuePair<float, float> _b)
{
return _a.Key.CompareTo(_b.Key);
}
}
}

View File

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

View File

@ -0,0 +1,80 @@
using System.Collections.Generic;
namespace RoadArchitect.Threading
{
public static class TerrainCalcsStatic
{
public static void RunMe(ref List<Terraforming.TempTerrainData> _TTDList, SplineC _spline, Road _road)
{
float Step = (_road.roadDefinition * 0.4f) / _spline.distance;
if (Step > 2f)
{
Step = 2f;
}
if (Step < 1f)
{
Step = 1f;
}
//float tDistance = tRoad.RoadWidth()*2f;
//Vector3 tVect,POS;
foreach (Terraforming.TempTerrainData TTD in _TTDList)
{
//float PrevHeight = 0f;
//float FinalMax = 1f;
//float StartMin = 0f;
//if(tSpline.bSpecialEndControlNode)
//{
// FinalMax = tSpline.mNodes[tSpline.GetNodeCount()-2].tTime;
//}
//if(tSpline.bSpecialStartControlNode)
//{
// StartMin = tSpline.mNodes[1].tTime;
//}
//if(tRoad.opt_MatchTerrain)
//{
RootUtils.StartProfiling(_road, "DoRects");
TerraformingThreaded.DoRects(_spline, TTD);
RootUtils.EndProfiling(_road);
//}
//else
//{
// for(float i=StartMin;i<=FinalMax;i+=Step)
// {
// if(tSpline.IsInBridgeTerrain(i))
// {
// float tFloat = tSpline.GetBridgeEnd(i);
// if(IsApproximately(tFloat,1f,0.00001f) || tFloat > 1f)
// {
// continue;
// }
// if(tFloat < 0f)
// {
// continue;
// }
// i = tFloat;
// }
// tSpline.GetSplineValue_Both(i,out tVect,out POS);
// PrevHeight = TerraformingThreaded.ProcessLineHeights(tSpline,ref tVect,ref POS,tDistance,TTD,PrevHeight);
// tSpline.HeightHistory.Add(new KeyValuePair<float,float>(i,PrevHeight*TTD.TerrainSize.y));
// }
//
// for(int i=0;i<TTD.cI;i++)
// {
// TTD.heights[TTD.cX[i],TTD.cY[i]] = TTD.cH[i];
// }
//}
}
_spline.HeightHistory.Sort(Compare1);
}
private static int Compare1(KeyValuePair<float, float> _a, KeyValuePair<float, float> _b)
{
return _a.Key.CompareTo(_b.Key);
}
}
}

View File

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

View File

@ -0,0 +1,182 @@
using System.Collections.Generic;
using UnityEngine;
namespace RoadArchitect
{
[System.Serializable]
public class TerrainHistoryMaker
{
#region "Vars"
public int terrainID;
public int heightmapResolution;
//Heights:
public int[] x1;
public int[] y1;
public float[] height;
public int Count;
//Details:
public int detailLayersCount;
public int[] detailsCount;
public int[] detailsX;
public int[] detailsY;
public int[] detailsOldValue;
//Trees:
public TerrainTreeInstance[] oldTrees;
public int treesCount;
#endregion
public void Nullify()
{
//Heights:
x1 = null;
y1 = null;
height = null;
detailsX = null;
detailsY = null;
detailsOldValue = null;
detailsCount = null;
//Trees:
oldTrees = null;
}
[System.Serializable]
public class TerrainTreeInstance
{
public float colorR;
public float colorG;
public float colorB;
public float colorA;
public float heightScale;
public float lightmapColorR;
public float lightmapColorG;
public float lightmapColorB;
public float lightmapColorA;
public float positionX;
public float positionY;
public float positionZ;
public int prototypeIndex;
public float widthScale;
// 4 bytes for int and float
//56 Bytes
}
/// <summary> Stores _trees into oldTrees </summary>
public void MakeRATrees(ref List<TreeInstance> _trees)
{
int tSize = _trees.Count;
oldTrees = new TerrainTreeInstance[tSize];
TerrainTreeInstance tTree = null;
TreeInstance xTree;
for (int index = 0; index < tSize; index++)
{
xTree = _trees[index];
tTree = new TerrainTreeInstance();
tTree.colorR = xTree.color.r;
tTree.colorG = xTree.color.g;
tTree.colorB = xTree.color.b;
tTree.colorA = xTree.color.a;
tTree.heightScale = xTree.heightScale;
tTree.lightmapColorR = xTree.lightmapColor.r;
tTree.lightmapColorG = xTree.lightmapColor.g;
tTree.lightmapColorB = xTree.lightmapColor.b;
tTree.lightmapColorA = xTree.lightmapColor.a;
tTree.positionX = xTree.position.x;
tTree.positionY = xTree.position.y;
tTree.positionZ = xTree.position.z;
tTree.prototypeIndex = xTree.prototypeIndex;
tTree.widthScale = xTree.widthScale;
oldTrees[index] = tTree;
}
}
/// <summary> Returns a new tree array copy of oldTrees </summary>
public TreeInstance[] MakeTrees()
{
if (oldTrees == null || oldTrees.Length < 1)
{
return null;
}
int tSize = oldTrees.Length;
TreeInstance[] tTrees = new TreeInstance[tSize];
TerrainTreeInstance tTree = null;
TreeInstance xTree;
for (int index = 0; index < tSize; index++)
{
tTree = oldTrees[index];
xTree = new TreeInstance();
xTree.color = new Color(tTree.colorR, tTree.colorG, tTree.colorB, tTree.colorA);
xTree.heightScale = tTree.heightScale;
xTree.lightmapColor = new Color(tTree.lightmapColorR, tTree.lightmapColorG, tTree.lightmapColorB, tTree.lightmapColorA);
xTree.position = new Vector3(tTree.positionX, tTree.positionY, tTree.positionZ);
xTree.prototypeIndex = tTree.prototypeIndex;
xTree.widthScale = tTree.widthScale;
tTrees[index] = xTree;
}
return tTrees;
}
/// <summary> Returns size of this terrain history </summary>
public int GetSize()
{
int tSize = 4;
if (x1 != null)
{
tSize += (x1.Length * 4);
tSize += 20;
}
if (y1 != null)
{
tSize += (y1.Length * 4);
tSize += 20;
}
if (height != null)
{
tSize += (height.Length * 4);
tSize += 20;
}
tSize += 4;
tSize += 1;
//Details:
tSize += 4;
if (detailsX != null)
{
tSize += (detailsX.Length * 4);
tSize += 20;
}
if (detailsY != null)
{
tSize += (detailsY.Length * 4);
tSize += 20;
}
if (detailsOldValue != null)
{
tSize += (detailsOldValue.Length * 4);
tSize += 20;
}
if (detailsCount != null)
{
tSize += (detailsCount.Length * 4);
tSize += 20;
}
tSize += 1;
//Trees:
if (oldTrees != null)
{
tSize += (oldTrees.Length * 56);
tSize += 20;
}
tSize += 4;
tSize += 1;
tSize += 1;
return tSize;
}
}
}

View File

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

View File

@ -0,0 +1,154 @@
#region "Imports"
using System.Collections.Generic;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;
using System.Runtime.Serialization;
#endregion
namespace RoadArchitect
{
public static class TerrainHistoryUtility
{
//http://forum.unity3d.com/threads/32647-C-Sharp-Binary-Serialization
//http://answers.unity3d.com/questions/363477/c-how-to-setup-a-binary-serialization.html
// === This is required to guarantee a fixed serialization assembly name, which Unity likes to randomize on each compile
// Do not change this
public sealed class VersionDeserializationBinder : SerializationBinder
{
public override System.Type BindToType(string assemblyName, string typeName)
{
if (!string.IsNullOrEmpty(assemblyName) && !string.IsNullOrEmpty(typeName))
{
System.Type typeToDeserialize = null;
assemblyName = System.Reflection.Assembly.GetExecutingAssembly().FullName;
// The following line of code returns the type.
typeToDeserialize = System.Type.GetType(string.Format("{0}, {1}", typeName, assemblyName));
return typeToDeserialize;
}
return null;
}
}
/// <summary> Saves the Terrain History to disk </summary>
public static void SaveTerrainHistory(List<TerrainHistoryMaker> _obj, Road _road)
{
string path = CheckNonAssetDirTH() + GetRoadTHFilename(ref _road);
if (string.IsNullOrEmpty(path) || path.Length < 2)
{
return;
}
Stream stream = File.Open(path, FileMode.Create);
BinaryFormatter bformatter = new BinaryFormatter();
bformatter.Binder = new VersionDeserializationBinder();
bformatter.Serialize(stream, _obj);
_road.TerrainHistoryByteSize = (stream.Length * 0.001f).ToString("n0") + " kb";
stream.Close();
}
/// <summary> Deletes the Terrain History from disk </summary>
public static void DeleteTerrainHistory(Road _road)
{
string path = CheckNonAssetDirTH() + GetRoadTHFilename(ref _road);
if (File.Exists(path))
{
File.Delete(path);
}
}
/// <summary> Loads the Terrain History from disk </summary>
public static List<TerrainHistoryMaker> LoadTerrainHistory(Road _road)
{
string path = CheckNonAssetDirTH() + GetRoadTHFilename(ref _road);
if (string.IsNullOrEmpty(path) || path.Length < 2)
{
return null;
}
if (!File.Exists(path))
{
return null;
}
List<TerrainHistoryMaker> result;
Stream stream = File.Open(path, FileMode.Open);
BinaryFormatter bFormatter = new BinaryFormatter();
bFormatter.Binder = new VersionDeserializationBinder();
result = (List<TerrainHistoryMaker>)bFormatter.Deserialize(stream);
stream.Close();
return result;
}
/// <summary> Generates the Terrain History file name </summary>
private static string GetRoadTHFilename(ref Road _road)
{
string sceneName;
sceneName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name;
sceneName = sceneName.Replace("/", "");
sceneName = sceneName.Replace(".", "");
string roadName = _road.roadSystem.transform.name.Replace("RoadArchitectSystem", "RAS") + "-" + _road.transform.name;
return sceneName + "-" + roadName + ".th";
}
/// <summary> Returns the path to the RoadArchitect folder where Terrain History is saved </summary>
public static string GetDirBase()
{
return UnityEngine.Application.dataPath.Replace("/Assets", "/RoadArchitect/");
}
/// <summary> Returns the path where Terrain History is saved </summary>
public static string GetTHDir()
{
string path = GetDirBase() + "TerrainHistory/";
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
return path;
}
/// <summary> Checks if RoadArchitect folder exists </summary>
public static string CheckRoadArchitectDirectory()
{
string path = GetDirBase();
if (!Directory.Exists(path))
{
Directory.CreateDirectory(path);
}
if (Directory.Exists(path))
{
return path + "/";
}
else
{
return "";
}
}
/// <summary> Returns RoadArchitect/TerrainHistory path or empty </summary>
public static string CheckNonAssetDirTH()
{
CheckRoadArchitectDirectory();
string path = GetTHDir();
if (Directory.Exists(path))
{
return path;
}
else
{
return "";
}
}
}
}

View File

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