From 04be0ad46ce0751bd3e3ebd905e759aba5b518bb Mon Sep 17 00:00:00 2001 From: in0finite Date: Sun, 1 Aug 2021 17:02:50 +0200 Subject: [PATCH] attempt to impl infinite water --- Assets/Scripts/Behaviours/World/Cell.cs | 10 +-- Assets/Scripts/Behaviours/World/Water.cs | 86 +++++++++++++++++++++++- 2 files changed, 89 insertions(+), 7 deletions(-) diff --git a/Assets/Scripts/Behaviours/World/Cell.cs b/Assets/Scripts/Behaviours/World/Cell.cs index 2001ae43..05769fbf 100644 --- a/Assets/Scripts/Behaviours/World/Cell.cs +++ b/Assets/Scripts/Behaviours/World/Cell.cs @@ -91,6 +91,8 @@ namespace SanAndreasUnity.Behaviours.World } } + public int WorldSize { get; } = 6000; + public float[] drawDistancesPerLayers = new float[] { 301, 801, 1501 }; private WorldSystemWithDistanceLevels _worldSystem; @@ -143,11 +145,9 @@ namespace SanAndreasUnity.Behaviours.World UnityEngine.Debug.Log("Num static geometries " + m_insts.Count); - uint worldSize = 6000; - _worldSystem = new WorldSystemWithDistanceLevels( this.drawDistancesPerLayers, - this.xzWorldSystemNumAreasPerDrawDistanceLevel.Select(_ => new WorldSystemParams { worldSize = worldSize, numAreasPerAxis = _ }).ToArray(), + this.xzWorldSystemNumAreasPerDrawDistanceLevel.Select(_ => new WorldSystemParams { worldSize = (uint) this.WorldSize, numAreasPerAxis = _ }).ToArray(), Enumerable.Range(0, this.drawDistancesPerLayers.Length).Select(_ => new WorldSystemParams { worldSize = this.yWorldSystemSize, numAreasPerAxis = this.yWorldSystemNumAreas }).ToArray(), this.OnAreaChangedVisibility); } @@ -196,7 +196,9 @@ namespace SanAndreasUnity.Behaviours.World if (Water != null) { - Water.Initialize(new WaterFile(Importing.Archive.ArchiveManager.PathToCaseSensitivePath(Config.GetPath("water_path")))); + Water.Initialize( + new WaterFile(Importing.Archive.ArchiveManager.PathToCaseSensitivePath(Config.GetPath("water_path"))), + Vector2.one * this.WorldSize); } } diff --git a/Assets/Scripts/Behaviours/World/Water.cs b/Assets/Scripts/Behaviours/World/Water.cs index 9f50f057..e08eb64e 100644 --- a/Assets/Scripts/Behaviours/World/Water.cs +++ b/Assets/Scripts/Behaviours/World/Water.cs @@ -10,7 +10,7 @@ namespace SanAndreasUnity.Behaviours.World public GameObject WaterPrefab; - public void Initialize(WaterFile file) + public void Initialize(WaterFile file, Vector2 worldSize) { if (this.WaterPrefab == null) { @@ -22,8 +22,16 @@ namespace SanAndreasUnity.Behaviours.World var faces = file.Faces.Where(f => (f.Flags & WaterFlags.Visible) == WaterFlags.Visible); - int totalNumVertexes = faces.Sum(f => f.Vertices.Length); - int totalNumIndexes = faces.Sum(f => (f.Vertices.Length - 2) * 3); + // we need total of 4 quads for "infinite" water: + // - upper side (from upper world boundary to positive infinity) + // - lower side (from lower world boundary to negative infinity) + // - left side (between first 2 quads) + // - right side (between first 2 quads) + + const int numQuadsForInfiniteWater = 4; + + int totalNumVertexes = faces.Sum(f => f.Vertices.Length) + numQuadsForInfiniteWater * GetNumVertexesForQuad(); + int totalNumIndexes = faces.Sum(f => (f.Vertices.Length - 2) * 3) + numQuadsForInfiniteWater * GetNumIndexesForQuad(); Vector3[] vertices = new Vector3[totalNumVertexes]; Vector3[] normals = new Vector3[totalNumVertexes]; @@ -52,6 +60,46 @@ namespace SanAndreasUnity.Behaviours.World indicesIndex += (face.Vertices.Length - 2) * 3; } + // add "infinite" water + + const float infiniteWaterOffset = 20000f; + // upper quad + CreateQuad( + new Vector2( -worldSize.x / 2f - infiniteWaterOffset, worldSize.y / 2f), + new Vector2(worldSize.x / 2f + infiniteWaterOffset, worldSize.y / 2f + infiniteWaterOffset), + vertices, + normals, + ref verticesIndex, + indices, + ref indicesIndex); + // lower quad + CreateQuad( + new Vector2( -worldSize.x / 2f - infiniteWaterOffset, - worldSize.y / 2f - infiniteWaterOffset), + new Vector2(worldSize.x / 2f + infiniteWaterOffset, - worldSize.y / 2f), + vertices, + normals, + ref verticesIndex, + indices, + ref indicesIndex); + // left quad + CreateQuad( + new Vector2( -worldSize.x / 2f - infiniteWaterOffset, - worldSize.y / 2f), + new Vector2(- worldSize.x / 2f, worldSize.y / 2f), + vertices, + normals, + ref verticesIndex, + indices, + ref indicesIndex); + // right quad + CreateQuad( + new Vector2( worldSize.x / 2f, - worldSize.y / 2f), + new Vector2(worldSize.x / 2f + infiniteWaterOffset, worldSize.y / 2f), + vertices, + normals, + ref verticesIndex, + indices, + ref indicesIndex); + var mesh = new Mesh(); mesh.vertices = vertices; @@ -66,5 +114,37 @@ namespace SanAndreasUnity.Behaviours.World go.GetComponent().sharedMesh = mesh; } + + void CreateQuad(Vector2 min, Vector2 max, Vector3[] vertexes, Vector3[] normals, ref int vertexIndex, int[] indexes, ref int indexesIndex) + { + vertexes[vertexIndex++] = new Vector3(min.x, 0f, min.y); // low left + vertexes[vertexIndex++] = new Vector3(max.x, 0f, min.y); // low right + vertexes[vertexIndex++] = new Vector3(min.x, 0f, max.y); // up left + vertexes[vertexIndex++] = new Vector3(max.x, 0f, max.y); // up right + + normals[vertexIndex - 4] = Vector3.up; + normals[vertexIndex - 3] = Vector3.up; + normals[vertexIndex - 2] = Vector3.up; + normals[vertexIndex - 1] = Vector3.up; + + // triangle 1: low left, low right, up right + // triangle 2: low left, up right, up left + + int lowLeft = vertexIndex - 4; + int lowRight = vertexIndex - 3; + int upLeft = vertexIndex - 2; + int upRight = vertexIndex - 1; + + indexes[indexesIndex++] = lowLeft; + indexes[indexesIndex++] = lowRight; + indexes[indexesIndex++] = upRight; + indexes[indexesIndex++] = lowLeft; + indexes[indexesIndex++] = upRight; + indexes[indexesIndex++] = upLeft; + } + + int GetNumVertexesForQuad() => 4; + + int GetNumIndexesForQuad() => 6; } } \ No newline at end of file