2024-11-19 11:48:21 +01:00

1185 lines
45 KiB
C#

using System.Collections.Generic;
using UnityEngine;
namespace RoadArchitect.Threading
{
public static class TerraformingThreaded
{
public class TerrainBoundsMaker
{
public List<Construction3DTri> triList;
public Construction2DRect constructRect;
public float MinI = 0f;
public float MaxI = 1f;
}
/*
private static Vector3 ProcessLineHeights_PrevVect = new Vector3(0f, 0f, 0f);
public static float ProcessLineHeights(SplineC tSpline, ref Vector3 tVect, ref Vector3 POS, float tDistance, Terraforming.TempTerrainData TTD, float PrevDesiredHeight)
{
Vector3 ShoulderR_rVect = new Vector3(0f, 0f, 0f);
Vector3 ShoulderL_lVect = new Vector3(0f, 0f, 0f);
float DesiredHeight = ProcessLineHeights_GetDesiredHeight(tVect, ref TTD, ref tSpline);
float nResult = 0f;
bool bIntersection = tSpline.IsNearIntersection(ref tVect, ref nResult);
if(bIntersection)
{
if(nResult < tVect.y)
{
tVect.y = nResult;
DesiredHeight = ProcessLineHeights_GetDesiredHeight(tVect, ref TTD, ref tSpline);
}
}
int x1 = 0, y1 = 0;
GetTempHeights_Coordinates(ref tVect, ref TTD, out x1, out y1);
bool bOverride = false;
int StepMod = (int) (1 / TTD.HMRatio);
for(float i = tDistance; i >= 1f; i -= StepMod)
{
ShoulderR_rVect = (tVect + new Vector3(i * POS.normalized.z, 0, i * -POS.normalized.x));
GetTempHeights_Coordinates(ref ShoulderR_rVect, ref TTD, out x1, out y1);
if(TTD.heights[x1, y1] > DesiredHeight)
{
bOverride = true;
}
if(bOverride || !TTD.tHeights[x1, y1])
{
TTD.tHeights[x1, y1] = true;
TTD.cX[TTD.cI] = x1;
TTD.cY[TTD.cI] = y1;
TTD.cH[TTD.cI] = DesiredHeight;
TTD.oldH[TTD.cI] = TTD.heights[x1, y1];
TTD.cI += 1;
}
bOverride = false;
ShoulderL_lVect = (tVect + new Vector3(i * -POS.normalized.z, 0, i * POS.normalized.x));
GetTempHeights_Coordinates(ref ShoulderL_lVect, ref TTD, out x1, out y1);
if(TTD.heights[x1, y1] > DesiredHeight)
{
bOverride = true;
}
if(bOverride || !TTD.tHeights[x1, y1])
{
TTD.tHeights[x1, y1] = true;
TTD.cX[TTD.cI] = x1;
TTD.cY[TTD.cI] = y1;
TTD.cH[TTD.cI] = DesiredHeight;
TTD.oldH[TTD.cI] = TTD.heights[x1, y1];
TTD.cI += 1;
}
bOverride = false;
}
GetTempHeights_Coordinates(ref tVect, ref TTD, out x1, out y1);
if(TTD.heights[x1, y1] > DesiredHeight || (tVect.y < ProcessLineHeights_PrevVect.y))
{
bOverride = true;
}
if(bOverride || !TTD.tHeights[x1, y1])
{
TTD.tHeights[x1, y1] = true;
TTD.cX[TTD.cI] = x1;
TTD.cY[TTD.cI] = y1;
if(tDistance > 15f && TTD.HMRatio > 0.24f)
{
TTD.cH[TTD.cI] = DesiredHeight - 0.0002f;
}
else
{
TTD.cH[TTD.cI] = DesiredHeight;
}
TTD.oldH[TTD.cI] = TTD.heights[x1, y1];
TTD.cI += 1;
}
ProcessLineHeights_PrevVect = tVect;
return DesiredHeight;
}
private static float ProcessLineHeights_GetDesiredHeight(Vector3 tVect, ref Terraforming.TempTerrainData TTD, ref SplineC tSpline)
{
return ((((tVect - TTD.TerrainPos).y) - tSpline.tRoad.opt_TerrainSubtract_Alt) / TTD.TerrainSize.y);
}
*/
/// <summary> Writes heightmap location of _vector into _x and _y </summary>
private static void GetTempHeightsCoordinates(ref Vector3 _vector, ref Terraforming.TempTerrainData _TTD, out int _x, out int _y)
{
//Get the normalized position of this game object relative to the terrain:
Vector3 tempCoord = (_vector - _TTD.TerrainPos);
Vector3 coord;
coord.x = tempCoord.x / _TTD.TerrainSize.x;
coord.y = tempCoord.y / _TTD.TerrainSize.y;
coord.z = tempCoord.z / _TTD.TerrainSize.z;
//Get the position of the terrain heightmap where this game object is:
_y = (int)(coord.x * _TTD.HM);
_x = (int)(coord.z * _TTD.HM);
}
/// <summary> Writes heightmap location of _vector into _x and _y </summary>
private static void GetTempDetailsCoordinates(ref Vector3 _vector, ref Terraforming.TempTerrainData _TTD, out int _x, out int _y)
{
//Get the normalized position of this game object relative to the terrain:
Vector3 tempCoord = (_vector - _TTD.TerrainPos);
Vector3 coord;
coord.x = tempCoord.x / _TTD.TerrainSize.x;
coord.y = tempCoord.y / _TTD.TerrainSize.y;
coord.z = tempCoord.z / _TTD.TerrainSize.z;
//Get the position of the terrain heightmap where this game object is:
_y = (int)(coord.x * _TTD.DetailMaxIndex);
_x = (int)(coord.z * _TTD.DetailMaxIndex);
}
//Privatized for obfuscate:
public static void DoRects(SplineC _spline, Terraforming.TempTerrainData _TTD)
{
DoRectsDo(ref _spline, ref _TTD);
}
private static void DoRectsDo(ref SplineC _spline, ref Terraforming.TempTerrainData _TTD)
{
float Sep = _spline.road.RoadWidth() * 0.5f;
float HeightSep = Sep + (_spline.road.matchHeightsDistance * 0.5f);
List<TerrainBoundsMaker> TBMList = new List<TerrainBoundsMaker>();
//List<RoadUtility.Construction3DTri> triList = new List<RoadUtility.Construction3DTri>();
List<Construction2DRect> TreerectList = new List<Construction2DRect>();
float tStep = _spline.road.roadDefinition / _spline.distance;
//tStep *= 0.5f;
//Start initializing the loop. Convuluted to handle special control nodes, so roads don't get rendered where they aren't supposed to, while still preserving the proper curvature.
float FinalMax = 1f;
float StartMin = 0f;
if (_spline.isSpecialEndControlNode)
{
//If control node, start after the control node:
FinalMax = _spline.nodes[_spline.GetNodeCount() - 2].time;
}
if (_spline.isSpecialStartControlNode)
{
//If ends in control node, end construction before the control node:
StartMin = _spline.nodes[1].time;
}
//Storage of incremental start values for the road connection mesh construction at the end of this function.
//float RoadConnection_StartMin1 = StartMin;
//Storage of incremental end values for the road connection mesh construction at the end of this function.
//float RoadConnection_FinalMax1 = FinalMax;
if (_spline.isSpecialEndNodeIsStartDelay)
{
//If there's a start delay (in meters), delay the start of road construction: Due to special control nodes for road connections or 3 way intersections.
StartMin += (_spline.specialEndNodeDelayStart / _spline.distance);
}
else if (_spline.isSpecialEndNodeIsEndDelay)
{
//If there's a end delay (in meters), cut early the end of road construction: Due to special control nodes for road connections or 3 way intersections.
FinalMax -= (_spline.specialEndNodeDelayEnd / _spline.distance);
}
//Storage of incremental start values for the road connection mesh construction at the end of this function.
//float RoadConnection_StartMin2 = StartMin;
//Storage of incremental end values for the road connection mesh construction at the end of this function.
//float RoadConnection_FinalMax2 = FinalMax;
FinalMax = FinalMax + tStep;
Vector3 tVect1 = default(Vector3);
Vector3 tVect2 = default(Vector3);
Vector3 POS1 = default(Vector3);
Vector3 POS2 = default(Vector3);
if (FinalMax > 1f)
{
FinalMax = 1f;
}
float tNext = 0f;
float fValue1, fValue2;
float fValueMod = _spline.road.roadDefinition / _spline.distance;
bool bIsPastInter = false;
float tIntStrength = 0f;
float tIntStrength2 = 0f;
//bool bMaxIntersection = false;
SplineN xNode = null;
float tIntHeight = 0f;
float tIntHeight2 = 0f;
RoadIntersection roadIntersection = null;
float T1SUB = 0f;
float T2SUB = 0f;
bool bIntStr1_Full = false;
bool bIntStr1_FullPrev = false;
bool bIntStr1_FullNext = false;
bool bIntStr2_Full = false;
bool bIntStr2_FullPrev = false;
bool bIntStr2_FullNext = false;
Vector3 tVect3 = default(Vector3);
List<int[]> tXYs = new List<int[]>();
float TreeClearDist = _spline.road.clearTreesDistance;
if (TreeClearDist < _spline.road.RoadWidth())
{
TreeClearDist = _spline.road.RoadWidth();
}
Construction2DRect tRect = null;
float tGrade = 0f;
for (float index = StartMin; index < FinalMax; index += tStep)
{
if (_spline.road.isHeightModificationEnabled)
{
if (index > 1f)
{
break;
}
tNext = index + tStep;
if (tNext > 1f)
{
break;
}
_spline.GetSplineValueBoth(index, out tVect1, out POS1);
if (tNext <= 1f)
{
_spline.GetSplineValueBoth(tNext, out tVect2, out POS2);
}
else
{
_spline.GetSplineValueBoth(1f, out tVect2, out POS2);
}
//Determine if intersection:
bIsPastInter = false;
//If past intersection
tIntStrength = _spline.IntersectionStrength(ref tVect1, ref tIntHeight, ref roadIntersection, ref bIsPastInter, ref index, ref xNode);
//if(IsApproximately(tIntStrength,1f,0.001f) || tIntStrength > 1f)
//{
// bMaxIntersection = true;
//}
//else
//{
// bMaxIntersection = false;
//}
tIntStrength2 = _spline.IntersectionStrength(ref tVect2, ref tIntHeight2, ref roadIntersection, ref bIsPastInter, ref index, ref xNode);
if (tIntStrength2 > 1f)
{
tIntStrength2 = 1f;
}
T1SUB = tVect1.y;
T2SUB = tVect2.y;
if (tIntStrength > 1f)
{
tIntStrength = 1f;
}
if (tIntStrength >= 0f)
{
// || IsApproximately(tIntStrength,0f,0.01f)){
if (RootUtils.IsApproximately(tIntStrength, 1f, 0.01f))
{
T1SUB = tIntHeight;
bIntStr1_Full = true;
bIntStr1_FullNext = false;
}
else
{
bIntStr1_Full = false;
bIntStr1_FullNext = (tIntStrength2 >= 1f);
if (!RootUtils.IsApproximately(tIntStrength, 0f, 0.01f))
{
T1SUB = (tIntStrength * tIntHeight) + ((1 - tIntStrength) * tVect1.y);
}
//if(tIntStrength <= 0f)
//{
// T1SUB = (tIntStrength*tIntHeight) + ((1-tIntStrength)*tVect1.y);
//}
}
if ((bIntStr1_Full && !bIntStr1_FullPrev) || (!bIntStr1_Full && bIntStr1_FullNext))
{
tGrade = _spline.GetCurrentNode(index).gradeToPrevValue;
if (tGrade < 0f)
{
T1SUB -= Mathf.Lerp(0.02f, roadIntersection.gradeMod, (tGrade / 20f) * -1f);
}
else
{
T1SUB -= Mathf.Lerp(0.02f, roadIntersection.gradeMod, tGrade / 20f);
}
//if(tGrade < 0f)
//{
// T1SUB *= -1f;
//}
}
else if (bIntStr1_Full && !bIntStr1_FullNext)
{
tGrade = _spline.GetCurrentNode(index).gradeToNextValue;
if (tGrade < 0f)
{
T1SUB -= Mathf.Lerp(0.02f, roadIntersection.gradeMod, (tGrade / 20f) * -1f);
}
else
{
T1SUB -= Mathf.Lerp(0.02f, roadIntersection.gradeMod, tGrade / 20f);
}
//if(tGrade < 0f)
//{
// T1SUB *= -1f;
//}
}
else
{
T1SUB -= 0.02f;
}
bIntStr1_FullPrev = bIntStr1_Full;
}
if (tIntStrength2 >= 0f || RootUtils.IsApproximately(tIntStrength2, 0f, 0.01f))
{
//if(!IsApproximately(tIntStrength,1f,0.01f)){
if (RootUtils.IsApproximately(tIntStrength, 1f, 0.01f))
{
bIntStr2_Full = true;
T2SUB = tIntHeight2;
}
else
{
bIntStr2_Full = false;
if (!RootUtils.IsApproximately(tIntStrength2, 0f, 0.01f))
{
T2SUB = (tIntStrength2 * tIntHeight) + ((1 - tIntStrength2) * tVect2.y);
}
//if(tIntStrength2 <= 0f)
//{
//T2SUB = (tIntStrength2*tIntHeight) + ((1-tIntStrength2)*tVect2.y);
//}
}
if ((bIntStr2_Full && !bIntStr2_FullPrev))
{
tGrade = _spline.GetCurrentNode(index).gradeToPrevValue;
if (tGrade < 0f)
{
T2SUB -= Mathf.Lerp(0.02f, roadIntersection.gradeMod, (tGrade / 20f) * -1f);
}
else
{
T2SUB -= Mathf.Lerp(0.02f, roadIntersection.gradeMod, tGrade / 20f);
}
//T2SUB -= tIntHeight2 - tVect2.y;
}
else if (bIntStr2_Full && !bIntStr2_FullNext)
{
tGrade = _spline.GetCurrentNode(index).gradeToNextValue;
if (tGrade < 0f)
{
T2SUB -= Mathf.Lerp(0.02f, roadIntersection.gradeMod, (tGrade / 20f) * -1f);
}
else
{
T2SUB -= Mathf.Lerp(0.02f, roadIntersection.gradeMod, tGrade / 20f);
}
//if(tGrade < 0f)
//{
// T2SUB *= -1f;
//}
//T2SUB -= tIntHeight2 - tVect2.y;
}
else if (!bIntStr2_Full)
{
if (tNext + tStep < 1f)
{
tVect3 = _spline.GetSplineValue(tNext + tStep, false);
tIntStrength2 = _spline.IntersectionStrength(ref tVect3, ref tIntHeight2, ref roadIntersection, ref bIsPastInter, ref index, ref xNode);
}
else
{
tIntStrength2 = 0f;
}
if (tIntStrength2 >= 1f)
{
T2SUB -= 0.06f;
}
else
{
T2SUB -= 0.02f;
}
}
else
{
T2SUB -= 0.02f;
}
bIntStr2_FullPrev = bIntStr2_Full;
}
fValue1 = index - fValueMod;
fValue2 = index + fValueMod;
if (fValue1 < 0)
{
fValue1 = 0;
}
if (fValue2 > 1)
{
fValue2 = 1;
}
tXYs.Add(CreateTris(fValue1, fValue2, ref tVect1, ref POS1, ref tVect2, ref POS2, Sep, ref TBMList, ref T1SUB, ref T2SUB, ref _TTD, HeightSep));
//Details and trees:
tRect = SetDetailCoords(index, ref tVect1, ref POS1, ref tVect2, ref POS2, _spline.road.clearDetailsDistance, TreeClearDist, ref _TTD, ref _spline);
if (_spline.road.isTreeModificationEnabled && tRect != null)
{
TreerectList.Add(tRect);
}
}
else
{
if (index > 1f)
{
break;
}
tNext = index + tStep;
if (tNext > 1f)
{
break;
}
_spline.GetSplineValueBoth(index, out tVect1, out POS1);
if (tNext <= 1f)
{
_spline.GetSplineValueBoth(tNext, out tVect2, out POS2);
}
else
{
_spline.GetSplineValueBoth(1f, out tVect2, out POS2);
}
//Details and trees:
tRect = SetDetailCoords(index, ref tVect1, ref POS1, ref tVect2, ref POS2, _spline.road.clearDetailsDistance, TreeClearDist, ref _TTD, ref _spline);
if (_spline.road.isTreeModificationEnabled && tRect != null)
{
TreerectList.Add(tRect);
}
}
}
RootUtils.StartProfiling(_spline.road, "DoRectsTree");
if (_spline.road.isTreeModificationEnabled && TreerectList != null && TreerectList.Count > 0)
{
int tCount = _TTD.TreeSize;
int jCount = TreerectList.Count;
Vector3 tVect3D = default(Vector3);
Vector2 tVect2D = default(Vector2);
TreeInstance tTree;
for (int i = 0; i < tCount; i++)
{
tTree = _TTD.TreesCurrent[i];
tVect3D = tTree.position;
tVect3D.x *= _TTD.TerrainSize.z;
tVect3D.y *= _TTD.TerrainSize.y;
tVect3D.z *= _TTD.TerrainSize.x;
tVect3D += _TTD.TerrainPos;
tVect2D.x = tVect3D.x;
tVect2D.y = tVect3D.z;
for (int j = 0; j < jCount; j++)
{
if (TreerectList[j].Contains(ref tVect2D))
{
_TTD.TreesOld.Add(_TTD.TreesCurrent[i]);
tTree = _TTD.TreesCurrent[i];
tTree.prototypeIndex = -2;
_TTD.TreesCurrent[i] = tTree;
_TTD.treesCount += 1;
break;
}
}
}
_TTD.TreesCurrent.RemoveAll(item => item.prototypeIndex < -1);
}
RootUtils.EndProfiling(_spline.road);
if (!_spline.road.isHeightModificationEnabled)
{
return;
}
////Temp testing:
//tSpline.mNodes[22].tTriList = new List<RoadUtility.Construction3DTri>();
//int tCount = triList.Count;
//for(int i=0;i<tCount;i++)
//{
// tSpline.mNodes[22].tTriList.Add(triList[i]);
//}
//tSpline.mNodes[22].tHMList = new List<Vector3>();
float tFloat = -1f;
Sep = _spline.road.RoadWidth() * 1.5f;
int k = 0;
int[] tXY = null;
int tXYsCount = tXYs.Count;
bool isBridge = false;
bool isTunnel = false;
for (float index = StartMin; index < FinalMax; index += tStep)
{
if (TBMList.Count > 0)
{
if (TBMList[0].MaxI < index)
{
CleanupTris(index, ref TBMList);
}
}
else
{
break;
}
//If in bridge mode:
if (_spline.IsInBridgeTerrain(index))
{
isBridge = true;
}
else
{
isBridge = false;
}
//If in tunnel mode:
if (_spline.IsInTunnelTerrain(index))
{
isTunnel = true;
}
else
{
isTunnel = false;
}
if (k < tXYsCount)
{
tXY = tXYs[k];
tFloat = ProcessCoordinateGrabber(ref index, ref _spline, ref _TTD, ref TBMList, ref tXY, isBridge, isTunnel);
if (!RootUtils.IsApproximately(tFloat, 0f, 0.0001f))
{
_spline.HeightHistory.Add(new KeyValuePair<float, float>(index, tFloat));
}
}
else
{
break;
}
k += 1;
}
}
private static void CleanupTris(float _currentI, ref List<TerrainBoundsMaker> _terrainBoundsList)
{
int mCount = _terrainBoundsList.Count;
int LastIndexToRemove = -1;
for (int index = 0; index < mCount; index++)
{
if (_terrainBoundsList[index].MaxI < _currentI)
{
LastIndexToRemove = index;
}
else
{
break;
}
}
if (LastIndexToRemove >= 0)
{
_terrainBoundsList.RemoveRange(0, LastIndexToRemove);
}
//
//mCount = rectList.Count;
//LastIndexToRemove = -1;
//for(int i=0;i<mCount;i++)
//{
// if(tList[i].MaxI < CurrentI)
// {
// LastIndexToRemove = i;
// }
// else
// {
// break;
// }
//}
//if(LastIndexToRemove >= 0)
//{
// rectList.RemoveRange(0,LastIndexToRemove);
//}
}
private static int[] CreateTris(float _i, float _i2, ref Vector3 _vect1, ref Vector3 _POS1, ref Vector3 _vect2, ref Vector3 _POS2, float _sep, ref List<TerrainBoundsMaker> _list, ref float _T1SUB, ref float _T2SUB, ref Terraforming.TempTerrainData _TTD, float _heightSep)
{
Vector3 lVect1 = (_vect1 + new Vector3(_sep * -_POS1.normalized.z, 0, _sep * _POS1.normalized.x));
Vector3 rVect1 = (_vect1 + new Vector3(_sep * _POS1.normalized.z, 0, _sep * -_POS1.normalized.x));
Vector3 lVect2 = (_vect2 + new Vector3(_sep * -_POS2.normalized.z, 0, _sep * _POS2.normalized.x));
Vector3 rVect2 = (_vect2 + new Vector3(_sep * _POS2.normalized.z, 0, _sep * -_POS2.normalized.x));
lVect1.y = _T1SUB;
rVect1.y = _T1SUB;
lVect2.y = _T2SUB;
rVect2.y = _T2SUB;
TerrainBoundsMaker TBM = new TerrainBoundsMaker();
TBM.triList = new List<Construction3DTri>();
TBM.triList.Add(new Construction3DTri(lVect1, rVect1, lVect2, _i, _i2));
TBM.triList.Add(new Construction3DTri(lVect2, rVect1, rVect2, _i, _i2));
Vector3 lVect1far = (_vect1 + new Vector3(_heightSep * -_POS1.normalized.z, 0, _heightSep * _POS1.normalized.x));
Vector3 rVect1far = (_vect1 + new Vector3(_heightSep * _POS1.normalized.z, 0, _heightSep * -_POS1.normalized.x));
Vector3 lVect2far = (_vect2 + new Vector3(_heightSep * -_POS2.normalized.z, 0, _heightSep * _POS2.normalized.x));
Vector3 rVect2far = (_vect2 + new Vector3(_heightSep * _POS2.normalized.z, 0, _heightSep * -_POS2.normalized.x));
lVect1far.y = lVect1.y;
lVect2far.y = lVect2.y;
rVect1far.y = rVect1.y;
rVect2far.y = rVect2.y;
TBM.triList.Add(new Construction3DTri(lVect1far, lVect1, lVect2far, _i, _i2));
TBM.triList.Add(new Construction3DTri(lVect2far, lVect1, lVect2, _i, _i2));
TBM.triList.Add(new Construction3DTri(rVect1, rVect1far, rVect2, _i, _i2));
TBM.triList.Add(new Construction3DTri(rVect2, rVect1far, rVect2far, _i, _i2));
TBM.constructRect = new Construction2DRect(new Vector2(lVect1far.x, lVect1far.z), new Vector2(rVect1far.x, rVect1far.z), new Vector2(rVect2far.x, rVect2far.z), new Vector2(lVect2far.x, lVect2far.z), 0f);
//tRect.MinI = i;
//tRect.MaxI = i2;
TBM.MinI = _i;
TBM.MaxI = _i2;
_list.Add(TBM);
int[] Xs = new int[4];
int[] Ys = new int[4];
int x1, y1;
GetTempHeightsCoordinates(ref lVect1far, ref _TTD, out x1, out y1);
Xs[0] = x1;
Ys[0] = y1;
GetTempHeightsCoordinates(ref lVect2far, ref _TTD, out x1, out y1);
Xs[1] = x1;
Ys[1] = y1;
GetTempHeightsCoordinates(ref rVect1far, ref _TTD, out x1, out y1);
Xs[2] = x1;
Ys[2] = y1;
GetTempHeightsCoordinates(ref rVect2far, ref _TTD, out x1, out y1);
Xs[3] = x1;
Ys[3] = y1;
int Min = Mathf.Min(Xs);
int Max = Mathf.Max(Xs);
Xs[0] = Min - 2;
Xs[2] = Max + 2;
Min = Mathf.Min(Ys);
Max = Mathf.Max(Ys);
Xs[1] = Min - 2;
Xs[3] = Max + 2;
return Xs;
}
private static Construction2DRect SetDetailCoords(float _param, ref Vector3 _vect1, ref Vector3 _POS1, ref Vector3 _vect2, ref Vector3 POS2, float _sep, float _treeSep, ref Terraforming.TempTerrainData _TTD, ref SplineC _spline)
{
Vector3 lVect1far = default(Vector3);
Vector3 rVect1far = default(Vector3);
Vector3 lVect2far = default(Vector3);
Vector3 rVect2far = default(Vector3);
bool isInBridge = _spline.IsInBridgeTerrain(_param);
bool isInTunnel = _spline.IsInTunnelTerrain(_param);
int x2, y2, x3, y3;
GetTempHeightsCoordinates(ref _vect1, ref _TTD, out x2, out y2);
if (x2 >= _TTD.HM)
{
x2 = -1;
}
if (y2 >= _TTD.HM)
{
y2 = -1;
}
if (x2 < 0)
{
x2 = -1;
}
if (y2 < 0)
{
y2 = -1;
}
if (x2 == -1)
{
return null;
}
if (y2 == -1)
{
return null;
}
float tDiff1 = ((_TTD.heights[x2, y2] * (float)_TTD.TerrainSize.y) - _vect1.y);
GetTempHeightsCoordinates(ref _vect2, ref _TTD, out x3, out y3);
if (x3 >= _TTD.HM)
{
x3 = -1;
}
if (y3 >= _TTD.HM)
{
y3 = -1;
}
if (x3 < 0)
{
x3 = -1;
}
if (y3 < 0)
{
y3 = -1;
}
if (x3 == -1)
{
return null;
}
if (y3 == -1)
{
return null;
}
float tDiff2 = ((_TTD.heights[x3, y3] * (float)_TTD.TerrainSize.y) - _vect2.y);
Construction2DRect tRect = null;
if (_spline.road.isTreeModificationEnabled)
{
bool isQuit = false;
if (x2 == -1)
{
isQuit = true;
}
if (y2 == -1)
{
isQuit = true;
}
if (isInBridge && !isQuit)
{
if (tDiff1 < 0f)
{
tDiff1 *= -1f;
}
if (tDiff2 < 0f)
{
tDiff2 *= -1f;
}
if (tDiff1 > _spline.road.clearTreesDistanceHeight)
{
isQuit = true;
}
if (tDiff2 > _spline.road.clearTreesDistanceHeight)
{
isQuit = true;
}
}
if (isInTunnel && !isQuit)
{
if (tDiff1 < 0f)
{
if ((tDiff1 * -1f) > _spline.road.clearTreesDistanceHeight)
{
isQuit = true;
}
}
else
{
if (tDiff1 > (_spline.road.clearTreesDistanceHeight * 0.1f))
{
isQuit = true;
}
}
if (tDiff2 < 0f)
{
if ((tDiff2 * -1f) > _spline.road.clearTreesDistanceHeight)
{
isQuit = true;
}
}
else
{
if (tDiff2 > (_spline.road.clearTreesDistanceHeight * 0.1f))
{
isQuit = true;
}
}
}
if (!isQuit)
{
_treeSep = _treeSep * 0.5f;
lVect1far = (_vect1 + new Vector3(_treeSep * -_POS1.normalized.z, 0, _treeSep * _POS1.normalized.x));
rVect1far = (_vect1 + new Vector3(_treeSep * _POS1.normalized.z, 0, _treeSep * -_POS1.normalized.x));
lVect2far = (_vect2 + new Vector3(_treeSep * -POS2.normalized.z, 0, _treeSep * POS2.normalized.x));
rVect2far = (_vect2 + new Vector3(_treeSep * POS2.normalized.z, 0, _treeSep * -POS2.normalized.x));
tRect = new Construction2DRect(new Vector2(lVect1far.x, lVect1far.z), new Vector2(rVect1far.x, rVect1far.z), new Vector2(rVect2far.x, rVect2far.z), new Vector2(lVect2far.x, lVect2far.z), 0f);
}
}
if (_spline.road.isDetailModificationEnabled)
{
if (isInBridge || isInTunnel)
{
if (tDiff1 < 0f)
{
tDiff1 *= -1f;
}
if (tDiff2 < 0f)
{
tDiff2 *= -1f;
}
bool isQuit = false;
if (x2 == -1)
{
isQuit = true;
}
if (y2 == -1)
{
isQuit = true;
}
if (tDiff1 > _spline.road.clearDetailsDistanceHeight)
{
isQuit = true;
}
if (tDiff2 > _spline.road.clearDetailsDistanceHeight)
{
isQuit = true;
}
if (isQuit)
{
return tRect;
}
}
_sep = _sep * 0.5f;
lVect1far = (_vect1 + new Vector3(_sep * -_POS1.normalized.z, 0, _sep * _POS1.normalized.x));
rVect1far = (_vect1 + new Vector3(_sep * _POS1.normalized.z, 0, _sep * -_POS1.normalized.x));
lVect2far = (_vect2 + new Vector3(_sep * -POS2.normalized.z, 0, _sep * POS2.normalized.x));
rVect2far = (_vect2 + new Vector3(_sep * POS2.normalized.z, 0, _sep * -POS2.normalized.x));
int[] Xs = new int[4];
int[] Ys = new int[4];
int x1, y1;
GetTempDetailsCoordinates(ref lVect1far, ref _TTD, out x1, out y1);
Xs[0] = x1;
Ys[0] = y1;
GetTempDetailsCoordinates(ref lVect2far, ref _TTD, out x1, out y1);
Xs[1] = x1;
Ys[1] = y1;
GetTempDetailsCoordinates(ref rVect1far, ref _TTD, out x1, out y1);
Xs[2] = x1;
Ys[2] = y1;
GetTempDetailsCoordinates(ref rVect2far, ref _TTD, out x1, out y1);
Xs[3] = x1;
Ys[3] = y1;
//if(TTD.DetailLayersCount == 1 && x1 > 0 && y1 > 0)
//{
// Debug.Log(Xs[0]+","+Ys[0] + " " + Xs[1]+","+Ys[1]);
//}
int MinX = Mathf.Min(Xs);
int MinY = Mathf.Min(Ys);
int MaxX = Mathf.Max(Xs);
int MaxY = Mathf.Max(Ys);
if (MinX >= _TTD.DetailMaxIndex)
{
MinX = _TTD.DetailMaxIndex - 1;
}
if (MinY >= _TTD.DetailMaxIndex)
{
MinY = _TTD.DetailMaxIndex - 1;
}
if (MaxX >= _TTD.DetailMaxIndex)
{
MaxX = _TTD.DetailMaxIndex - 1;
}
if (MaxY >= _TTD.DetailMaxIndex)
{
MaxY = _TTD.DetailMaxIndex - 1;
}
if (MinX < 0)
{
MinX = 0;
}
if (MinY < 0)
{
MinY = 0;
}
if (MaxX < 0)
{
MaxX = 0;
}
if (MaxY < 0)
{
MaxY = 0;
}
//int DetailI = 0;
RootUtils.StartProfiling(_spline.road, "Dorectsdetails");
int tInt = 0;
for (int index = MinX; index <= MaxX; index++)
{
for (int k = MinY; k <= MaxY; k++)
{
//Bitfield for identification:
tInt = k;
tInt = tInt << 16;
tInt = tInt | (ushort)index;
if (!_TTD.DetailHasProcessed.Contains(tInt))
{
//for(int h=0;h<TTD.DetailLayersCount;h++)
//{
// if(TTD.DetailLayersSkip.Contains(h))
// {
// continue;
// }
// if(!TTD.DetailHasProcessed[h][i,k]){// && TTD.DetailValues[h][i,k] > 0){
_TTD.MainDetailsX.Add((ushort)index);
_TTD.MainDetailsY.Add((ushort)k);
//DetailI = TTD.DetailsI[h];
//TTD.DetailsX[h].Add((ushort)i);
//TTD.DetailsY[h].Add((ushort)k);
//TTD.DetailsX[h][DetailI] = (ushort)i;
//TTD.DetailsY[h][DetailI] = (ushort)k;
//TTD.OldDetailsValue[h][DetailI] = (ushort)TTD.DetailValues[h][i,k];
//TTD.DetailValues[h][i,k] = 0;
//TTD.DetailsI[h]+=1;
//}
_TTD.DetailHasProcessed.Add(tInt);
}
}
}
RootUtils.EndProfiling(_spline.road);
}
return tRect;
}
private static float ProcessCoordinateGrabber(ref float _param, ref SplineC _spline, ref Terraforming.TempTerrainData _TTD, ref List<TerrainBoundsMaker> _terrainList, ref int[] _XY, bool _isBridge, bool _isTunnel)
{
int MinX = _XY[0];
int MinY = _XY[1];
int MaxX = _XY[2];
int MaxY = _XY[3];
if (MinX >= _TTD.TerrainMaxIndex)
{
MinX = _TTD.TerrainMaxIndex - 1;
}
if (MinY >= _TTD.TerrainMaxIndex)
{
MinY = _TTD.TerrainMaxIndex - 1;
}
if (MaxX >= _TTD.TerrainMaxIndex)
{
MaxX = _TTD.TerrainMaxIndex - 1;
}
if (MaxY >= _TTD.TerrainMaxIndex)
{
MaxY = _TTD.TerrainMaxIndex - 1;
}
if (MinX < 0)
{
MinX = 0;
}
if (MinY < 0)
{
MinY = 0;
}
if (MaxX < 0)
{
MaxX = 0;
}
if (MaxY < 0)
{
MaxY = 0;
}
Vector3 xVect = default(Vector3);
bool isAdjusted = false;
float tHeight = -1f;
float tReturnFloat = 0f;
for (int index = MinX; index <= MaxX; index++)
{
for (int k = MinY; k <= MaxY; k++)
{
if (_TTD.tHeights[index, k] != true)
{
if (_TTD.cX.Length <= _TTD.Count)
{
break;
}
xVect = ConvertTerrainCoordToWorldVect(index, k, _TTD.heights[index, k], ref _TTD);
AdjustedTerrainVectTri(ref _param, out isAdjusted, out tHeight, ref xVect, ref _terrainList, _isBridge, _isTunnel);
if (isAdjusted)
{
tHeight -= _spline.road.matchTerrainSubtraction;
if (tHeight < 0f)
{
tHeight = 0f;
}
xVect.y = tHeight;
tHeight = ((tHeight) / _TTD.TerrainSize.y);
//Set height values:
_TTD.tHeights[index, k] = true;
_TTD.cX[_TTD.Count] = (ushort)index;
_TTD.cY[_TTD.Count] = (ushort)k;
_TTD.oldH[_TTD.Count] = _TTD.heights[index, k];
_TTD.heights[index, k] = tHeight;
_TTD.Count += 1;
tReturnFloat = xVect.y;
}
}
else
{
xVect = ConvertTerrainCoordToWorldVect(index, k, _TTD.heights[index, k], ref _TTD);
AdjustedTerrainVectTri(ref _param, out isAdjusted, out tHeight, ref xVect, ref _terrainList, _isBridge, _isTunnel);
if (isAdjusted)
{
tHeight -= _spline.road.matchTerrainSubtraction;
if (tHeight < 0f)
{
tHeight = 0f;
}
tReturnFloat = tHeight;
}
}
}
}
if (_isBridge && RootUtils.IsApproximately(tReturnFloat, 0f, 0.0001f))
{
tReturnFloat = _spline.GetSplineValue(_param, false).y;
}
return tReturnFloat;
}
private static Vector3 ConvertTerrainCoordToWorldVect(int _x, int _y, float _height, ref Terraforming.TempTerrainData _TTD)
{
//Get the normalized position of this game object relative to the terrain:
float x1 = _x / ((float)_TTD.HM - 1f);
x1 = x1 * _TTD.TerrainSize.x;
float z1 = _y / ((float)_TTD.HM - 1f);
z1 = z1 * _TTD.TerrainSize.z;
float y1 = _height * _TTD.TerrainSize.y;
Vector3 xVect = new Vector3(z1, y1, x1);
xVect += _TTD.TerrainPos;
return xVect;
}
private static void AdjustedTerrainVectTri(ref float _param, out bool _isAdjusted, out float _height, ref Vector3 _vect, ref List<TerrainBoundsMaker> _terrainList, bool _isBridge, bool _isTunnel)
{
float OrigHeight = _vect.y;
int mCount = _terrainList.Count;
int tCount = 0;
Construction3DTri tTri;
TerrainBoundsMaker TBM;
_isAdjusted = false;
_height = 0f;
Vector2 t2D = new Vector2(_vect.x, _vect.z);
for (int index = 0; index < mCount; index++)
{
TBM = _terrainList[index];
if (_param < TBM.MinI)
{
return;
}
if (_param > TBM.MaxI)
{
continue;
}
if (TBM.constructRect.Contains(ref t2D))
{
tCount = TBM.triList.Count;
for (int k = 0; k < tCount; k++)
{
tTri = TBM.triList[k];
if (tTri.Contains2D(ref t2D))
{
_height = tTri.LinePlaneIntersection(ref _vect).y;
if (_isBridge)
{
if (OrigHeight > (_height - 0.03f))
{
_height -= 0.03f;
_isAdjusted = true;
return;
}
}
else if (_isTunnel)
{
if (OrigHeight < (_height + 0.03f))
{
_height += 0.03f;
_isAdjusted = true;
return;
}
}
else
{
_isAdjusted = true;
return;
}
}
}
}
}
}
}
}