This commit is contained in:
runette committed 2024-04-22 15:52:51 +01:00
commit e0afef912e
1285 files changed
+83219

No files matched your search

@@ -0,0 +1,416 @@
using System.Collections.Generic;
using System.Diagnostics;
using UnityEngine;
using Mapbox.Unity.MeshGeneration.Data;
using Mapbox.Unity.Map;
using Mapbox.Map;
using Mapbox.Utils;
using Debug = UnityEngine.Debug;
namespace Mapbox.Unity.MeshGeneration.Factories.TerrainStrategies
{
public class MeshDataArray
{
public Vector3[] Vertices;
public Vector3[] Normals;
public int[] Triangles;
public Vector2[] Uvs;
}
public class ElevatedTerrainStrategy : TerrainStrategy, IElevationBasedTerrainStrategy
{
private Dictionary<UnwrappedTileId, Mesh> _meshData;
private MeshData _currentTileMeshData;
private Dictionary<UnityTile, MeshDataArray> _cachedMeshDataArrays;
private Dictionary<UnwrappedTileId, MeshDataArray> _dataArrays;
private Dictionary<int, MeshDataArray> _meshSamples;
private List<Vector3> _newVertexList;
private List<Vector3> _newNormalList;
private List<Vector2> _newUvList;
private List<int> _newTriangleList;
private Vector3 _newDir;
private int _vertA, _vertB, _vertC;
private int _counter;
public override int RequiredVertexCount
{
get { return _elevationOptions.modificationOptions.sampleCount * _elevationOptions.modificationOptions.sampleCount; }
}
public override void Initialize(ElevationLayerProperties elOptions)
{
base.Initialize(elOptions);
_meshSamples = new Dictionary<int, MeshDataArray>();
_dataArrays = new Dictionary<UnwrappedTileId, MeshDataArray>();
_cachedMeshDataArrays = new Dictionary<UnityTile, MeshDataArray>();
_meshData = new Dictionary<UnwrappedTileId, Mesh>();
_currentTileMeshData = new MeshData();
var sampleCountSquare = _elevationOptions.modificationOptions.sampleCount * _elevationOptions.modificationOptions.sampleCount;
_newVertexList = new List<Vector3>(sampleCountSquare);
_newNormalList = new List<Vector3>(sampleCountSquare);
_newUvList = new List<Vector2>(sampleCountSquare);
_newTriangleList = new List<int>();
}
public override void RegisterTile(UnityTile tile)
{
if (_elevationOptions.unityLayerOptions.addToLayer && tile.gameObject.layer != _elevationOptions.unityLayerOptions.layerId)
{
tile.gameObject.layer = _elevationOptions.unityLayerOptions.layerId;
}
if (tile.MeshFilter.sharedMesh.vertexCount != RequiredVertexCount || !_cachedMeshDataArrays.ContainsKey(tile))
{
tile.MeshFilter.sharedMesh.Clear();
if (_meshSamples.ContainsKey(_elevationOptions.modificationOptions.sampleCount))
{
var newMesh = _meshSamples[_elevationOptions.modificationOptions.sampleCount];
tile.MeshFilter.sharedMesh.vertices = newMesh.Vertices;
tile.MeshFilter.sharedMesh.normals = newMesh.Normals;
tile.MeshFilter.sharedMesh.triangles = newMesh.Triangles;
tile.MeshFilter.sharedMesh.uv = newMesh.Uvs;
}
else
{
//TODO remoev tile dependency from CreateBaseMesh method
var newMesh = CreateBaseMesh(tile, _elevationOptions.modificationOptions.sampleCount);
_meshSamples.Add(_elevationOptions.modificationOptions.sampleCount, newMesh);
tile.MeshFilter.sharedMesh.vertices = newMesh.Vertices;
tile.MeshFilter.sharedMesh.normals = newMesh.Normals;
tile.MeshFilter.sharedMesh.triangles = newMesh.Triangles;
tile.MeshFilter.sharedMesh.uv = newMesh.Uvs;
}
if (!_dataArrays.ContainsKey(tile.UnwrappedTileId))
{
_dataArrays.Add(tile.UnwrappedTileId, new MeshDataArray()
{
Normals = tile.MeshFilter.sharedMesh.normals,
Vertices = tile.MeshFilter.sharedMesh.vertices,
Triangles = tile.MeshFilter.sharedMesh.triangles
});
}
}
else
{
_dataArrays.Add(tile.UnwrappedTileId, _cachedMeshDataArrays[tile]);
_cachedMeshDataArrays.Remove(tile);
}
tile.ElevationType = TileTerrainType.Elevated;
GenerateTerrainMesh(tile);
}
public override void UnregisterTile(UnityTile tile)
{
_meshData.Remove(tile.UnwrappedTileId);
if (_dataArrays.ContainsKey(tile.UnwrappedTileId))
{
_cachedMeshDataArrays.Add(tile, _dataArrays[tile.UnwrappedTileId]);
_dataArrays.Remove(tile.UnwrappedTileId);
}
}
public override void DataErrorOccurred(UnityTile t, TileErrorEventArgs e)
{
ResetToFlatMesh(t);
}
public override void PostProcessTile(UnityTile tile)
{
}
#region mesh gen
private MeshDataArray CreateBaseMesh(UnityTile tile, int sampleCount)
{
//TODO use arrays instead of lists
_newVertexList.Clear();
_newNormalList.Clear();
_newUvList.Clear();
_newTriangleList.Clear();
for (float y = 0; y < sampleCount; y++)
{
var yrat = y / (sampleCount - 1);
for (float x = 0; x < sampleCount; x++)
{
var xrat = x / (sampleCount - 1);
var xx = Mathd.Lerp(tile.Rect.Min.x, tile.Rect.Max.x, xrat);
var yy = Mathd.Lerp(tile.Rect.Min.y, tile.Rect.Max.y, yrat);
_newVertexList.Add(new Vector3(
(float) (xx - tile.Rect.Center.x) * tile.TileScale,
0,
(float) (yy - tile.Rect.Center.y) * tile.TileScale));
_newNormalList.Add(Mapbox.Unity.Constants.Math.Vector3Up);
_newUvList.Add(new Vector2(x * 1f / (sampleCount - 1), 1 - (y * 1f / (sampleCount - 1))));
}
}
int vertA, vertB, vertC;
for (int y = 0; y < sampleCount - 1; y++)
{
for (int x = 0; x < sampleCount - 1; x++)
{
vertA = (y * sampleCount) + x;
vertB = (y * sampleCount) + x + sampleCount + 1;
vertC = (y * sampleCount) + x + sampleCount;
_newTriangleList.Add(vertA);
_newTriangleList.Add(vertB);
_newTriangleList.Add(vertC);
vertA = (y * sampleCount) + x;
vertB = (y * sampleCount) + x + 1;
vertC = (y * sampleCount) + x + sampleCount + 1;
_newTriangleList.Add(vertA);
_newTriangleList.Add(vertB);
_newTriangleList.Add(vertC);
}
}
var mesh = new MeshDataArray();
mesh.Vertices = _newVertexList.ToArray();
mesh.Normals = _newNormalList.ToArray();
mesh.Uvs = _newUvList.ToArray();
mesh.Triangles = _newTriangleList.ToArray();
return mesh;
}
private Vector3[] _verts;
private Vector3[] _normals;
private Vector3[] _targetVerts;
private Vector3[] _targetNormals;
private void GenerateTerrainMesh(UnityTile tile)
{
_verts = _dataArrays[tile.UnwrappedTileId].Vertices;
_normals = _dataArrays[tile.UnwrappedTileId].Normals;
var _sampleCount = _elevationOptions.modificationOptions.sampleCount;
var hd = tile.HeightData;
var ts = tile.TileScale;
for (float y = 0; y < _sampleCount; y++)
{
for (float x = 0; x < _sampleCount; x++)
{
_verts[(int) (y * _sampleCount + x)] = new Vector3(
_verts[(int) (y * _sampleCount + x)].x,
hd[((int)((1 - y / (_sampleCount - 1)) * 255) * 256) + ((int)(x / (_sampleCount - 1) * 255))] * ts,
_verts[(int) (y * _sampleCount + x)].z);
_normals[(int) (y * _sampleCount + x)] = Mapbox.Unity.Constants.Math.Vector3Zero;
}
}
FixStitches(tile.UnwrappedTileId, _verts, _normals);
tile.MeshFilter.sharedMesh.vertices = _verts;
tile.MeshFilter.sharedMesh.RecalculateNormals();
tile.MeshFilter.sharedMesh.RecalculateBounds();
if (!_meshData.ContainsKey(tile.UnwrappedTileId))
{
_meshData.Add(tile.UnwrappedTileId, tile.MeshFilter.sharedMesh);
}
if (_elevationOptions.colliderOptions.addCollider)
{
var meshCollider = tile.Collider as MeshCollider;
if (meshCollider)
{
meshCollider.sharedMesh = tile.MeshFilter.sharedMesh;
}
}
}
private void ResetToFlatMesh(UnityTile tile)
{
if (tile.MeshFilter.sharedMesh.vertexCount == 0)
{
CreateBaseMesh(tile, _elevationOptions.modificationOptions.sampleCount);
}
else
{
tile.MeshFilter.sharedMesh.GetVertices(_currentTileMeshData.Vertices);
tile.MeshFilter.sharedMesh.GetNormals(_currentTileMeshData.Normals);
_counter = _currentTileMeshData.Vertices.Count;
for (int i = 0; i < _counter; i++)
{
_currentTileMeshData.Vertices[i] = new Vector3(
_currentTileMeshData.Vertices[i].x,
0,
_currentTileMeshData.Vertices[i].z);
_currentTileMeshData.Normals[i] = Mapbox.Unity.Constants.Math.Vector3Up;
}
tile.MeshFilter.sharedMesh.SetVertices(_currentTileMeshData.Vertices);
tile.MeshFilter.sharedMesh.SetNormals(_currentTileMeshData.Normals);
tile.MeshFilter.sharedMesh.RecalculateBounds();
}
}
/// <summary>
/// Checkes all neighbours of the given tile and stitches the edges to achieve a smooth mesh surface.
/// </summary>
/// <param name="tileId">UnwrappedTileId of the tile being processed.</param>
/// <param name="mesh"></param>
private void FixStitches(UnwrappedTileId tileId, Vector3[] verts, Vector3[] normals)
{
var _sampleCount = _elevationOptions.modificationOptions.sampleCount;
var meshVertCount = verts.Length;
if (_dataArrays.ContainsKey(tileId.North))
{
_targetVerts = _dataArrays[tileId.North].Vertices;
_targetNormals = _dataArrays[tileId.North].Normals;
for (int i = 0; i < _sampleCount; i++)
{
//just snapping the y because vertex pos is relative and we'll have to do tile pos + vertex pos for x&z otherwise
verts[i] = new Vector3(
verts[i].x,
_targetVerts[meshVertCount - _sampleCount + i].y,
verts[i].z);
normals[i] = new Vector3(_targetNormals[meshVertCount - _sampleCount + i].x,
_targetNormals[meshVertCount - _sampleCount + i].y,
_targetNormals[meshVertCount - _sampleCount + i].z);
}
}
if (_dataArrays.ContainsKey(tileId.South))
{
_targetVerts = _dataArrays[tileId.South].Vertices;
_targetNormals = _dataArrays[tileId.South].Normals;
for (int i = 0; i < _sampleCount; i++)
{
verts[meshVertCount - _sampleCount + i] = new Vector3(
verts[meshVertCount - _sampleCount + i].x,
_targetVerts[i].y,
verts[meshVertCount - _sampleCount + i].z);
normals[meshVertCount - _sampleCount + i] = new Vector3(
_targetNormals[i].x,
_targetNormals[i].y,
_targetNormals[i].z);
}
}
if (_dataArrays.ContainsKey(tileId.West))
{
_targetVerts = _dataArrays[tileId.West].Vertices;
_targetNormals = _dataArrays[tileId.West].Normals;
for (int i = 0; i < _sampleCount; i++)
{
verts[i * _sampleCount] = new Vector3(
verts[i * _sampleCount].x,
_targetVerts[i * _sampleCount + _sampleCount - 1].y,
verts[i * _sampleCount].z);
normals[i * _sampleCount] = new Vector3(
_targetNormals[i * _sampleCount + _sampleCount - 1].x,
_targetNormals[i * _sampleCount + _sampleCount - 1].y,
_targetNormals[i * _sampleCount + _sampleCount - 1].z);
}
}
if (_dataArrays.ContainsKey(tileId.East))
{
_targetVerts = _dataArrays[tileId.East].Vertices;
_targetNormals = _dataArrays[tileId.East].Normals;
for (int i = 0; i < _sampleCount; i++)
{
verts[i * _sampleCount + _sampleCount - 1] = new Vector3(
verts[i * _sampleCount + _sampleCount - 1].x,
_targetVerts[i * _sampleCount].y,
verts[i * _sampleCount + _sampleCount - 1].z);
normals[i * _sampleCount + _sampleCount - 1] = new Vector3(
_targetNormals[i * _sampleCount].x,
_targetNormals[i * _sampleCount].y,
_targetNormals[i * _sampleCount].z);
}
}
if (_dataArrays.ContainsKey(tileId.NorthWest))
{
_targetVerts = _dataArrays[tileId.NorthWest].Vertices;
_targetNormals = _dataArrays[tileId.NorthWest].Normals;
verts[0] = new Vector3(
verts[0].x,
_targetVerts[meshVertCount - 1].y,
verts[0].z);
normals[0] = new Vector3(
_targetNormals[meshVertCount - 1].x,
_targetNormals[meshVertCount - 1].y,
_targetNormals[meshVertCount - 1].z);
}
if (_dataArrays.ContainsKey(tileId.NorthEast))
{
_targetVerts = _dataArrays[tileId.NorthEast].Vertices;
_targetNormals = _dataArrays[tileId.NorthEast].Normals;
verts[_sampleCount - 1] = new Vector3(
verts[_sampleCount - 1].x,
_targetVerts[meshVertCount - _sampleCount].y,
verts[_sampleCount - 1].z);
normals[_sampleCount - 1] = new Vector3(
_targetNormals[meshVertCount - _sampleCount].x,
_targetNormals[meshVertCount - _sampleCount].y,
_targetNormals[meshVertCount - _sampleCount].z);
}
if (_dataArrays.ContainsKey(tileId.SouthWest))
{
_targetVerts = _dataArrays[tileId.SouthWest].Vertices;
_targetNormals = _dataArrays[tileId.SouthWest].Normals;
verts[meshVertCount - _sampleCount] = new Vector3(
verts[meshVertCount - _sampleCount].x,
_targetVerts[_sampleCount - 1].y,
verts[meshVertCount - _sampleCount].z);
normals[meshVertCount - _sampleCount] = new Vector3(
_targetNormals[_sampleCount - 1].x,
_targetNormals[_sampleCount - 1].y,
_targetNormals[_sampleCount - 1].z);
}
if (_dataArrays.ContainsKey(tileId.SouthEast))
{
_targetVerts = _dataArrays[tileId.SouthEast].Vertices;
_targetNormals = _dataArrays[tileId.SouthEast].Normals;
verts[meshVertCount - 1] = new Vector3(
verts[meshVertCount - 1].x,
_targetVerts[0].y,
verts[meshVertCount - 1].z);
normals[meshVertCount - 1] = new Vector3(
_targetNormals[0].x,
_targetNormals[0].y,
_targetNormals[0].z);
}
}
#endregion
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: ea9b70aa9455c614f8701116ede4599d
timeCreated: 1522755494
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,534 @@
using System.Collections.Generic;
using UnityEngine;
using Mapbox.Unity.MeshGeneration.Data;
using Mapbox.Unity.Map;
using Mapbox.Map;
using Mapbox.Utils;
namespace Mapbox.Unity.MeshGeneration.Factories.TerrainStrategies
{
public class ElevatedTerrainWithSidesStrategy : TerrainStrategy, IElevationBasedTerrainStrategy
{
Mesh _stitchTarget;
protected Dictionary<UnwrappedTileId, Mesh> _meshData;
private MeshData _currentTileMeshData;
private MeshData _stitchTargetMeshData;
private List<Vector3> _newVertexList;
private List<Vector3> _newNormalList;
private List<Vector2> _newUvList;
private List<int> _newTriangleList;
private Vector3 _newDir;
private int _vertA, _vertB, _vertC;
private int _counter;
public override int RequiredVertexCount
{
get { return _elevationOptions.modificationOptions.sampleCount * _elevationOptions.modificationOptions.sampleCount
+ (4 * _elevationOptions.modificationOptions.sampleCount); }
}
public override void Initialize(ElevationLayerProperties elOptions)
{
_elevationOptions = elOptions;
_meshData = new Dictionary<UnwrappedTileId, Mesh>();
_currentTileMeshData = new MeshData();
_stitchTargetMeshData = new MeshData();
var sampleCountSquare = _elevationOptions.modificationOptions.sampleCount * _elevationOptions.modificationOptions.sampleCount;
_newVertexList = new List<Vector3>(sampleCountSquare);
_newNormalList = new List<Vector3>(sampleCountSquare);
_newUvList = new List<Vector2>(sampleCountSquare);
_newTriangleList = new List<int>();
}
public override void RegisterTile(UnityTile tile)
{
if (_elevationOptions.unityLayerOptions.addToLayer && tile.gameObject.layer != _elevationOptions.unityLayerOptions.layerId)
{
tile.gameObject.layer = _elevationOptions.unityLayerOptions.layerId;
}
if (tile.RasterDataState != Enums.TilePropertyState.Loaded)
{
if (_elevationOptions.sideWallOptions.isActive)
{
var firstMat = tile.MeshRenderer.materials[0];
tile.MeshRenderer.materials = new Material[2]
{
firstMat,
_elevationOptions.sideWallOptions.wallMaterial
};
}
}
if (tile.MeshFilter.sharedMesh.vertexCount != RequiredVertexCount)
{
CreateBaseMesh(tile);
}
if (_elevationOptions.colliderOptions.addCollider && tile.Collider == null)
{
tile.gameObject.AddComponent<MeshCollider>();
}
GenerateTerrainMesh(tile);
}
public override void DataErrorOccurred(UnityTile t, TileErrorEventArgs e)
{
ResetToFlatMesh(t);
}
private void CreateBaseMesh(UnityTile tile)
{
//TODO use arrays instead of lists
_newVertexList.Clear();
_newNormalList.Clear();
_newUvList.Clear();
_newTriangleList.Clear();
var _sampleCount = _elevationOptions.modificationOptions.sampleCount;
for (float y = 0; y < _sampleCount; y++)
{
var yrat = y / (_sampleCount - 1);
for (float x = 0; x < _sampleCount; x++)
{
var xrat = x / (_sampleCount - 1);
var xx = Mathd.Lerp(tile.Rect.Min.x, tile.Rect.Max.x, xrat);
var yy = Mathd.Lerp(tile.Rect.Min.y, tile.Rect.Max.y, yrat);
_newVertexList.Add(new Vector3(
(float)(xx - tile.Rect.Center.x) * tile.TileScale,
0,
(float)(yy - tile.Rect.Center.y) * tile.TileScale));
_newNormalList.Add(Mapbox.Unity.Constants.Math.Vector3Up);
_newUvList.Add(new Vector2(x * 1f / (_sampleCount - 1), 1 - (y * 1f / (_sampleCount - 1))));
}
}
int vertA, vertB, vertC;
for (int y = 0; y < _sampleCount - 1; y++)
{
for (int x = 0; x < _sampleCount - 1; x++)
{
vertA = (y * _sampleCount) + x;
vertB = (y * _sampleCount) + x + _sampleCount + 1;
vertC = (y * _sampleCount) + x + _sampleCount;
_newTriangleList.Add(vertA);
_newTriangleList.Add(vertB);
_newTriangleList.Add(vertC);
vertA = (y * _sampleCount) + x;
vertB = (y * _sampleCount) + x + 1;
vertC = (y * _sampleCount) + x + _sampleCount + 1;
_newTriangleList.Add(vertA);
_newTriangleList.Add(vertB);
_newTriangleList.Add(vertC);
}
}
var sideVertBase = _newVertexList.Count;
var lastRow = (_sampleCount - 1) * _sampleCount;
var baseTriList = new List<int>();
for (int x = 0; x < _sampleCount; x++)
{
//side wall
//024
//135
_newVertexList.Add(_newVertexList[x]);
_newVertexList.Add(new Vector3(
_newVertexList[x].x,
-_elevationOptions.sideWallOptions.wallHeight,
_newVertexList[x].z));
_newNormalList.Add(Mapbox.Unity.Constants.Math.Vector3Forward);
_newNormalList.Add(Mapbox.Unity.Constants.Math.Vector3Forward);
_newUvList.Add(new Vector2(_newUvList[x * _sampleCount].y, 1));
_newUvList.Add(new Vector2(_newUvList[x * _sampleCount].y, 0));
//---
_newVertexList.Add(_newVertexList[x * _sampleCount]);
_newVertexList.Add(new Vector3(
_newVertexList[x * _sampleCount].x,
-_elevationOptions.sideWallOptions.wallHeight,
_newVertexList[x * _sampleCount].z));
_newNormalList.Add(Vector3.left);
_newNormalList.Add(Vector3.left);
_newUvList.Add(new Vector2(_newUvList[x * _sampleCount].y, 1));
_newUvList.Add(new Vector2(_newUvList[x * _sampleCount].y, 0));
//---
_newVertexList.Add(_newVertexList[(x + 1) * _sampleCount - 1]);
_newVertexList.Add(new Vector3(
_newVertexList[(x + 1) * _sampleCount - 1].x,
-_elevationOptions.sideWallOptions.wallHeight,
_newVertexList[(x + 1) * _sampleCount - 1].z));
_newNormalList.Add(Vector3.right);
_newNormalList.Add(Vector3.right);
_newUvList.Add(new Vector2(_newUvList[x * _sampleCount].y, 1));
_newUvList.Add(new Vector2(_newUvList[x * _sampleCount].y, 0));
//---
_newVertexList.Add(_newVertexList[lastRow + x]);
_newVertexList.Add(new Vector3(
_newVertexList[lastRow + x].x,
-_elevationOptions.sideWallOptions.wallHeight,
_newVertexList[lastRow + x].z));
_newNormalList.Add(Vector3.back);
_newNormalList.Add(Vector3.back);
_newUvList.Add(new Vector2(_newUvList[x * _sampleCount].y, 1));
_newUvList.Add(new Vector2(_newUvList[x * _sampleCount].y, 0));
if (x > 0)
{
baseTriList.Add(sideVertBase + 8 * x);
baseTriList.Add(sideVertBase + 8 * x - 8);
baseTriList.Add(sideVertBase + 8 * x - 8 + 1);
baseTriList.Add(sideVertBase + 8 * x);
baseTriList.Add(sideVertBase + 8 * x - 8 + 1);
baseTriList.Add(sideVertBase + 8 * x + 1);
//---
baseTriList.Add(sideVertBase + 8 * x + 2);
baseTriList.Add(sideVertBase + 8 * x - 8 + 1 + 2);
baseTriList.Add(sideVertBase + 8 * x - 8 + 2);
baseTriList.Add(sideVertBase + 8 * x + 2);
baseTriList.Add(sideVertBase + 8 * x + 1 + 2);
baseTriList.Add(sideVertBase + 8 * x - 8 + 1 + 2);
//---
baseTriList.Add(sideVertBase + 8 * x + 4);
baseTriList.Add(sideVertBase + 8 * x - 8 + 4);
baseTriList.Add(sideVertBase + 8 * x - 8 + 1 + 4);
baseTriList.Add(sideVertBase + 8 * x + 4);
baseTriList.Add(sideVertBase + 8 * x - 8 + 1 + 4);
baseTriList.Add(sideVertBase + 8 * x + 1 + 4);
//---
baseTriList.Add(sideVertBase + 8 * x + 6);
baseTriList.Add(sideVertBase + 8 * x - 8 + 1 + 6);
baseTriList.Add(sideVertBase + 8 * x - 8 + 6);
baseTriList.Add(sideVertBase + 8 * x + 6);
baseTriList.Add(sideVertBase + 8 * x + 1 + 6);
baseTriList.Add(sideVertBase + 8 * x - 8 + 1 + 6);
}
}
var mesh = tile.MeshFilter.mesh;
mesh.SetVertices(_newVertexList);
mesh.SetNormals(_newNormalList);
mesh.SetUVs(0, _newUvList);
mesh.subMeshCount = 2;
mesh.SetTriangles(_newTriangleList, 0);
mesh.SetTriangles(baseTriList, 1);
}
public override void UnregisterTile(UnityTile tile)
{
_meshData.Remove(tile.UnwrappedTileId);
}
/// <summary>
/// Creates the non-flat terrain mesh, using a grid by defined resolution (_sampleCount). Vertex order goes right & up. Normals are calculated manually and UV map is fitted/stretched 1-1.
/// Any additional scripts or logic, like MeshCollider or setting layer, can be done here.
/// </summary>
/// <param name="tile"></param>
// <param name="heightMultiplier">Multiplier for queried height value</param>
private void GenerateTerrainMesh(UnityTile tile)
{
tile.MeshFilter.sharedMesh.GetVertices(_currentTileMeshData.Vertices);
tile.MeshFilter.sharedMesh.GetNormals(_currentTileMeshData.Normals);
var _sampleCount = _elevationOptions.modificationOptions.sampleCount;
int sideStart = _sampleCount * _sampleCount;
for (float y = 0; y < _sampleCount; y++)
{
for (float x = 0; x < _sampleCount; x++)
{
_currentTileMeshData.Vertices[(int)(y * _sampleCount + x)] = new Vector3(
_currentTileMeshData.Vertices[(int)(y * _sampleCount + x)].x,
tile.QueryHeightData(x / (_sampleCount - 1), 1 - y / (_sampleCount - 1)),
_currentTileMeshData.Vertices[(int)(y * _sampleCount + x)].z);
_currentTileMeshData.Normals[(int)(y * _sampleCount + x)] = Mapbox.Unity.Constants.Math.Vector3Zero;
if (y == 0)
{
_currentTileMeshData.Vertices[(int)(sideStart + 8 * x)] = _currentTileMeshData.Vertices[(int)(y * _sampleCount + x)];
}
else if (y == _sampleCount - 1)
{
_currentTileMeshData.Vertices[(int)(sideStart + 8 * x + 6)] = _currentTileMeshData.Vertices[(int)(y * _sampleCount + x)];
}
if (x == 0)
{
_currentTileMeshData.Vertices[(int)(sideStart + 8 * y + 2)] = _currentTileMeshData.Vertices[(int)(y * _sampleCount + x)];
}
else if (x == _sampleCount - 1)
{
_currentTileMeshData.Vertices[(int)(sideStart + 8 * y + 4)] = _currentTileMeshData.Vertices[(int)(y * _sampleCount + x)];
}
}
}
tile.MeshFilter.sharedMesh.SetVertices(_currentTileMeshData.Vertices);
for (int y = 0; y < _sampleCount - 1; y++)
{
for (int x = 0; x < _sampleCount - 1; x++)
{
_vertA = (y * _sampleCount) + x;
_vertB = (y * _sampleCount) + x + _sampleCount + 1;
_vertC = (y * _sampleCount) + x + _sampleCount;
_newDir = Vector3.Cross(_currentTileMeshData.Vertices[_vertB] - _currentTileMeshData.Vertices[_vertA], _currentTileMeshData.Vertices[_vertC] - _currentTileMeshData.Vertices[_vertA]);
_currentTileMeshData.Normals[_vertA] += _newDir;
_currentTileMeshData.Normals[_vertB] += _newDir;
_currentTileMeshData.Normals[_vertC] += _newDir;
_vertA = (y * _sampleCount) + x;
_vertB = (y * _sampleCount) + x + 1;
_vertC = (y * _sampleCount) + x + _sampleCount + 1;
_newDir = Vector3.Cross(_currentTileMeshData.Vertices[_vertB] - _currentTileMeshData.Vertices[_vertA], _currentTileMeshData.Vertices[_vertC] - _currentTileMeshData.Vertices[_vertA]);
_currentTileMeshData.Normals[_vertA] += _newDir;
_currentTileMeshData.Normals[_vertB] += _newDir;
_currentTileMeshData.Normals[_vertC] += _newDir;
}
}
FixStitches(tile.UnwrappedTileId, _currentTileMeshData);
tile.MeshFilter.sharedMesh.SetNormals(_currentTileMeshData.Normals);
tile.MeshFilter.sharedMesh.SetVertices(_currentTileMeshData.Vertices);
tile.MeshFilter.sharedMesh.RecalculateBounds();
if (!_meshData.ContainsKey(tile.UnwrappedTileId))
{
_meshData.Add(tile.UnwrappedTileId, tile.MeshFilter.mesh);
}
if (_elevationOptions.colliderOptions.addCollider)
{
var meshCollider = tile.Collider as MeshCollider;
if (meshCollider)
{
meshCollider.sharedMesh = tile.MeshFilter.mesh;
}
}
}
private void ResetToFlatMesh(UnityTile tile)
{
if (tile.MeshFilter.sharedMesh.vertexCount == 0)
{
CreateBaseMesh(tile);
}
else
{
tile.MeshFilter.sharedMesh.GetVertices(_currentTileMeshData.Vertices);
tile.MeshFilter.sharedMesh.GetNormals(_currentTileMeshData.Normals);
_counter = _currentTileMeshData.Vertices.Count;
for (int i = 0; i < _counter; i++)
{
_currentTileMeshData.Vertices[i] = new Vector3(
_currentTileMeshData.Vertices[i].x,
0,
_currentTileMeshData.Vertices[i].z);
_currentTileMeshData.Normals[i] = Mapbox.Unity.Constants.Math.Vector3Up;
}
tile.MeshFilter.sharedMesh.SetVertices(_currentTileMeshData.Vertices);
tile.MeshFilter.sharedMesh.SetNormals(_currentTileMeshData.Normals);
tile.MeshFilter.sharedMesh.RecalculateBounds();
}
}
/// <summary>
/// Checkes all neighbours of the given tile and stitches the edges to achieve a smooth mesh surface.
/// </summary>
/// <param name="tileId"></param>
/// <param name="mesh"></param>
private void FixStitches(UnwrappedTileId tileId, MeshData mesh)
{
var _sampleCount = _elevationOptions.modificationOptions.sampleCount;
var meshVertCount = _sampleCount * _sampleCount;
_stitchTarget = null;
_meshData.TryGetValue(tileId.North, out _stitchTarget);
if (_stitchTarget != null)
{
_stitchTarget.GetVertices(_stitchTargetMeshData.Vertices);
_stitchTarget.GetNormals(_stitchTargetMeshData.Normals);
for (int i = 0; i < _sampleCount; i++)
{
//just snapping the y because vertex pos is relative and we'll have to do tile pos + vertex pos for x&z otherwise
mesh.Vertices[i] = new Vector3(
mesh.Vertices[i].x,
_stitchTargetMeshData.Vertices[meshVertCount - _sampleCount + i].y,
mesh.Vertices[i].z);
mesh.Vertices[meshVertCount + (8 * i)] = mesh.Vertices[i];
mesh.Normals[i] = new Vector3(_stitchTargetMeshData.Normals[meshVertCount - _sampleCount + i].x,
_stitchTargetMeshData.Normals[meshVertCount - _sampleCount + i].y,
_stitchTargetMeshData.Normals[meshVertCount - _sampleCount + i].z);
}
}
_stitchTarget = null;
_meshData.TryGetValue(tileId.South, out _stitchTarget);
if (_stitchTarget != null)
{
_stitchTarget.GetVertices(_stitchTargetMeshData.Vertices);
_stitchTarget.GetNormals(_stitchTargetMeshData.Normals);
for (int i = 0; i < _sampleCount; i++)
{
mesh.Vertices[meshVertCount - _sampleCount + i] = new Vector3(
mesh.Vertices[meshVertCount - _sampleCount + i].x,
_stitchTargetMeshData.Vertices[i].y,
mesh.Vertices[meshVertCount - _sampleCount + i].z);
mesh.Vertices[meshVertCount + 6 + (8 * i)] = mesh.Vertices[meshVertCount - _sampleCount + i];
mesh.Normals[meshVertCount - _sampleCount + i] = new Vector3(
_stitchTargetMeshData.Normals[i].x,
_stitchTargetMeshData.Normals[i].y,
_stitchTargetMeshData.Normals[i].z);
}
}
_stitchTarget = null;
_meshData.TryGetValue(tileId.West, out _stitchTarget);
if (_stitchTarget != null)
{
_stitchTarget.GetVertices(_stitchTargetMeshData.Vertices);
_stitchTarget.GetNormals(_stitchTargetMeshData.Normals);
for (int i = 0; i < _sampleCount; i++)
{
mesh.Vertices[i * _sampleCount] = new Vector3(
mesh.Vertices[i * _sampleCount].x,
_stitchTargetMeshData.Vertices[i * _sampleCount + _sampleCount - 1].y,
mesh.Vertices[i * _sampleCount].z);
mesh.Vertices[meshVertCount + 2 + (8 * i)] = mesh.Vertices[i * _sampleCount];
mesh.Normals[i * _sampleCount] = new Vector3(
_stitchTargetMeshData.Normals[i * _sampleCount + _sampleCount - 1].x,
_stitchTargetMeshData.Normals[i * _sampleCount + _sampleCount - 1].y,
_stitchTargetMeshData.Normals[i * _sampleCount + _sampleCount - 1].z);
}
}
_stitchTarget = null;
_meshData.TryGetValue(tileId.East, out _stitchTarget);
if (_stitchTarget != null)
{
_stitchTarget.GetVertices(_stitchTargetMeshData.Vertices);
_stitchTarget.GetNormals(_stitchTargetMeshData.Normals);
for (int i = 0; i < _sampleCount; i++)
{
mesh.Vertices[i * _sampleCount + _sampleCount - 1] = new Vector3(
mesh.Vertices[i * _sampleCount + _sampleCount - 1].x,
_stitchTargetMeshData.Vertices[i * _sampleCount].y,
mesh.Vertices[i * _sampleCount + _sampleCount - 1].z);
mesh.Vertices[meshVertCount + 4 + (8 * i)] = mesh.Vertices[i * _sampleCount + _sampleCount - 1];
mesh.Normals[i * _sampleCount + _sampleCount - 1] = new Vector3(
_stitchTargetMeshData.Normals[i * _sampleCount].x,
_stitchTargetMeshData.Normals[i * _sampleCount].y,
_stitchTargetMeshData.Normals[i * _sampleCount].z);
}
}
_stitchTarget = null;
_meshData.TryGetValue(tileId.NorthWest, out _stitchTarget);
if (_stitchTarget != null)
{
_stitchTarget.GetVertices(_stitchTargetMeshData.Vertices);
_stitchTarget.GetNormals(_stitchTargetMeshData.Normals);
mesh.Vertices[0] = new Vector3(
mesh.Vertices[0].x,
_stitchTargetMeshData.Vertices[meshVertCount - 1].y,
mesh.Vertices[0].z);
mesh.Normals[0] = new Vector3(
_stitchTargetMeshData.Normals[meshVertCount - 1].x,
_stitchTargetMeshData.Normals[meshVertCount - 1].y,
_stitchTargetMeshData.Normals[meshVertCount - 1].z);
}
_stitchTarget = null;
_meshData.TryGetValue(tileId.NorthEast, out _stitchTarget);
if (_stitchTarget != null)
{
_stitchTarget.GetVertices(_stitchTargetMeshData.Vertices);
_stitchTarget.GetNormals(_stitchTargetMeshData.Normals);
mesh.Vertices[_sampleCount - 1] = new Vector3(
mesh.Vertices[_sampleCount - 1].x,
_stitchTargetMeshData.Vertices[meshVertCount - _sampleCount].y,
mesh.Vertices[_sampleCount - 1].z);
mesh.Normals[_sampleCount - 1] = new Vector3(
_stitchTargetMeshData.Normals[meshVertCount - _sampleCount].x,
_stitchTargetMeshData.Normals[meshVertCount - _sampleCount].y,
_stitchTargetMeshData.Normals[meshVertCount - _sampleCount].z);
}
_stitchTarget = null;
_meshData.TryGetValue(tileId.SouthWest, out _stitchTarget);
if (_stitchTarget != null)
{
_stitchTarget.GetVertices(_stitchTargetMeshData.Vertices);
_stitchTarget.GetNormals(_stitchTargetMeshData.Normals);
mesh.Vertices[meshVertCount - _sampleCount] = new Vector3(
mesh.Vertices[meshVertCount - _sampleCount].x,
_stitchTargetMeshData.Vertices[_sampleCount - 1].y,
mesh.Vertices[meshVertCount - _sampleCount].z);
mesh.Normals[meshVertCount - _sampleCount] = new Vector3(
_stitchTargetMeshData.Normals[_sampleCount - 1].x,
_stitchTargetMeshData.Normals[_sampleCount - 1].y,
_stitchTargetMeshData.Normals[_sampleCount - 1].z);
}
_stitchTarget = null;
_meshData.TryGetValue(tileId.SouthEast, out _stitchTarget);
if (_stitchTarget != null)
{
_stitchTarget.GetVertices(_stitchTargetMeshData.Vertices);
_stitchTarget.GetNormals(_stitchTargetMeshData.Normals);
mesh.Vertices[meshVertCount - 1] = new Vector3(
mesh.Vertices[meshVertCount - 1].x,
_stitchTargetMeshData.Vertices[0].y,
mesh.Vertices[meshVertCount - 1].z);
mesh.Normals[meshVertCount - 1] = new Vector3(
_stitchTargetMeshData.Normals[0].x,
_stitchTargetMeshData.Normals[0].y,
_stitchTargetMeshData.Normals[0].z);
}
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 3d67aa1b17136294b92c1a5f4d9d867a
timeCreated: 1522755493
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,4 @@
public interface IElevationBasedTerrainStrategy
{
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 0629e9d95db9602439cbd191b7c35260
timeCreated: 1522756350
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,109 @@
using System.Collections.Generic;
using UnityEngine;
using Mapbox.Unity.MeshGeneration.Data;
using Mapbox.Unity.Map;
using Mapbox.Utils;
using Mapbox.Unity.Utilities;
namespace Mapbox.Unity.MeshGeneration.Factories.TerrainStrategies
{
public class FlatSphereTerrainStrategy : TerrainStrategy
{
public float Radius { get { return _elevationOptions.modificationOptions.earthRadius; } }
public override int RequiredVertexCount
{
get { return _elevationOptions.modificationOptions.sampleCount * _elevationOptions.modificationOptions.sampleCount; }
}
public override void Initialize(ElevationLayerProperties elOptions)
{
_elevationOptions = elOptions;
}
public override void RegisterTile(UnityTile tile)
{
if (_elevationOptions.unityLayerOptions.addToLayer && tile.gameObject.layer != _elevationOptions.unityLayerOptions.layerId)
{
tile.gameObject.layer = _elevationOptions.unityLayerOptions.layerId;
}
if ((int)tile.ElevationType != (int)ElevationLayerType.GlobeTerrain ||
tile.MeshFilter.sharedMesh.vertexCount != RequiredVertexCount)
{
tile.MeshFilter.sharedMesh.Clear();
tile.ElevationType = TileTerrainType.Globe;
}
GenerateTerrainMesh(tile);
}
void GenerateTerrainMesh(UnityTile tile)
{
var verts = new List<Vector3>();
var _sampleCount = _elevationOptions.modificationOptions.sampleCount;
var _radius = _elevationOptions.modificationOptions.earthRadius;
for (float x = 0; x < _sampleCount; x++)
{
for (float y = 0; y < _sampleCount; y++)
{
var xx = Mathf.Lerp((float)tile.Rect.Min.x, ((float)tile.Rect.Min.x + (float)tile.Rect.Size.x),
x / (_sampleCount - 1));
var yy = Mathf.Lerp((float)tile.Rect.Max.y, ((float)tile.Rect.Max.y + (float)tile.Rect.Size.y),
y / (_sampleCount - 1));
var ll = Conversions.MetersToLatLon(new Vector2d(xx, yy));
var latitude = (float)(Mathf.Deg2Rad * ll.x);
var longitude = (float)(Mathf.Deg2Rad * ll.y);
float xPos = (_radius) * Mathf.Cos(latitude) * Mathf.Cos(longitude);
float zPos = (_radius) * Mathf.Cos(latitude) * Mathf.Sin(longitude);
float yPos = (_radius) * Mathf.Sin(latitude);
var pp = new Vector3(xPos, yPos, zPos);
verts.Add(pp);
}
}
var trilist = new List<int>();
for (int y = 0; y < _sampleCount - 1; y++)
{
for (int x = 0; x < _sampleCount - 1; x++)
{
trilist.Add((y * _sampleCount) + x);
trilist.Add((y * _sampleCount) + x + _sampleCount + 1);
trilist.Add((y * _sampleCount) + x + _sampleCount);
trilist.Add((y * _sampleCount) + x);
trilist.Add((y * _sampleCount) + x + 1);
trilist.Add((y * _sampleCount) + x + _sampleCount + 1);
}
}
var uvlist = new List<Vector2>();
var step = 1f / (_sampleCount - 1);
for (int i = 0; i < _sampleCount; i++)
{
for (int j = 0; j < _sampleCount; j++)
{
uvlist.Add(new Vector2(i * step, (j * step)));
}
}
tile.MeshFilter.sharedMesh.SetVertices(verts);
tile.MeshFilter.sharedMesh.SetTriangles(trilist, 0);
tile.MeshFilter.sharedMesh.SetUVs(0, uvlist);
tile.MeshFilter.sharedMesh.RecalculateBounds();
tile.MeshFilter.sharedMesh.RecalculateNormals();
tile.transform.localPosition = Mapbox.Unity.Constants.Math.Vector3Zero;
}
public override void UnregisterTile(UnityTile tile)
{
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 830e93932f0e72840a1f6d588dce1a4a
timeCreated: 1522755493
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,196 @@
using System.Collections.Generic;
using UnityEngine;
using Mapbox.Unity.MeshGeneration.Data;
using Mapbox.Unity.Map;
using Mapbox.Unity.Utilities;
namespace Mapbox.Unity.MeshGeneration.Factories.TerrainStrategies
{
public class FlatTerrainStrategy : TerrainStrategy
{
MeshDataArray _cachedQuad;
public override int RequiredVertexCount
{
get { return 4; }
}
public override void Initialize(ElevationLayerProperties elOptions)
{
_elevationOptions = elOptions;
}
public override void RegisterTile(UnityTile tile)
{
if (_elevationOptions.unityLayerOptions.addToLayer && tile.gameObject.layer != _elevationOptions.unityLayerOptions.layerId)
{
tile.gameObject.layer = _elevationOptions.unityLayerOptions.layerId;
}
if (tile.RasterDataState != Enums.TilePropertyState.Loaded ||
tile.MeshFilter.sharedMesh.vertexCount != RequiredVertexCount)
{
if (_elevationOptions.sideWallOptions.isActive)
{
var firstMat = tile.MeshRenderer.materials[0];
tile.MeshRenderer.materials = new Material[2]
{
firstMat,
_elevationOptions.sideWallOptions.wallMaterial
};
}
}
if ((int)tile.ElevationType != (int)ElevationLayerType.FlatTerrain)
{
tile.MeshFilter.sharedMesh.Clear();
// HACK: This is here in to make the system trigger a finished state.
GetQuad(tile, _elevationOptions.sideWallOptions.isActive);
tile.ElevationType = TileTerrainType.Flat;
}
if (_elevationOptions.colliderOptions.addCollider)
{
var meshCollider = tile.Collider as MeshCollider;
if (meshCollider)
{
meshCollider.sharedMesh = tile.MeshFilter.sharedMesh;
}
}
}
private void GetQuad(UnityTile tile, bool buildSide)
{
if (_cachedQuad != null)
{
var mesh = tile.MeshFilter.sharedMesh;
mesh.vertices = _cachedQuad.Vertices;
mesh.normals = _cachedQuad.Normals;
mesh.triangles = _cachedQuad.Triangles;
mesh.uv = _cachedQuad.Uvs;
}
else
{
if (buildSide)
{
BuildQuadWithSides(tile);
}
else
{
BuildQuad(tile);
}
}
}
private void BuildQuad(UnityTile tile)
{
var unityMesh = tile.MeshFilter.sharedMesh;
var verts = new Vector3[4];
var norms = new Vector3[4];
verts[0] = tile.TileScale * ((tile.Rect.Min - tile.Rect.Center).ToVector3xz());
verts[1] = tile.TileScale * (new Vector3((float)(tile.Rect.Max.x - tile.Rect.Center.x), 0, (float)(tile.Rect.Min.y - tile.Rect.Center.y)));
verts[2] = tile.TileScale * ((tile.Rect.Max - tile.Rect.Center).ToVector3xz());
verts[3] = tile.TileScale * (new Vector3((float)(tile.Rect.Min.x - tile.Rect.Center.x), 0, (float)(tile.Rect.Max.y - tile.Rect.Center.y)));
norms[0] = Mapbox.Unity.Constants.Math.Vector3Up;
norms[1] = Mapbox.Unity.Constants.Math.Vector3Up;
norms[2] = Mapbox.Unity.Constants.Math.Vector3Up;
norms[3] = Mapbox.Unity.Constants.Math.Vector3Up;
unityMesh.vertices = verts;
unityMesh.normals = norms;
var trilist = new int[6] { 0, 1, 2, 0, 2, 3 };
unityMesh.triangles = trilist;
var uvlist = new Vector2[4]
{
new Vector2(0,1),
new Vector2(1,1),
new Vector2(1,0),
new Vector2(0,0)
};
unityMesh.uv = uvlist;
_cachedQuad = new MeshDataArray()
{
Vertices = verts,
Normals = norms,
Triangles = trilist,
Uvs = uvlist
};
}
private void BuildQuadWithSides(UnityTile tile)
{
var unityMesh = tile.MeshFilter.sharedMesh;
var verts = new Vector3[20];
var norms = new Vector3[20];
verts[0] = tile.TileScale * ((tile.Rect.Min - tile.Rect.Center).ToVector3xz());
verts[1] = tile.TileScale * (new Vector3((float)(tile.Rect.Max.x - tile.Rect.Center.x), 0, (float)(tile.Rect.Min.y - tile.Rect.Center.y)));
verts[2] = tile.TileScale * ((tile.Rect.Max - tile.Rect.Center).ToVector3xz());
verts[3] = tile.TileScale * (new Vector3((float)(tile.Rect.Min.x - tile.Rect.Center.x), 0, (float)(tile.Rect.Max.y - tile.Rect.Center.y)));
norms[0] = Mapbox.Unity.Constants.Math.Vector3Up;
norms[1] = Mapbox.Unity.Constants.Math.Vector3Up;
norms[2] = Mapbox.Unity.Constants.Math.Vector3Up;
norms[3] = Mapbox.Unity.Constants.Math.Vector3Up;
//verts goes
//01
//32
unityMesh.subMeshCount = 2;
Vector3 norm = Mapbox.Unity.Constants.Math.Vector3Up;
for (int i = 0; i < 4; i++)
{
verts[4 * (i + 1)] = verts[i];
verts[4 * (i + 1) + 1] = verts[i + 1];
verts[4 * (i + 1) + 2] = verts[i] + new Vector3(0, -_elevationOptions.sideWallOptions.wallHeight, 0);
verts[4 * (i + 1) + 3] = verts[i + 1] + new Vector3(0, -_elevationOptions.sideWallOptions.wallHeight, 0);
norm = Vector3.Cross(verts[4 * (i + 1) + 1] - verts[4 * (i + 1) + 2], verts[4 * (i + 1)] - verts[4 * (i + 1) + 1]).normalized;
norms[4 * (i + 1)] = norm;
norms[4 * (i + 1) + 1] = norm;
norms[4 * (i + 1) + 2] = norm;
norms[4 * (i + 1) + 3] = norm;
}
unityMesh.vertices = verts;
unityMesh.normals = norms;
var trilist = new List<int>(6) { 0, 1, 2, 0, 2, 3 };
unityMesh.SetTriangles(trilist, 0);
trilist = new List<int>(8);
for (int i = 0; i < 4; i++)
{
trilist.Add(4 * (i + 1));
trilist.Add(4 * (i + 1) + 2);
trilist.Add(4 * (i + 1) + 1);
trilist.Add(4 * (i + 1) + 1);
trilist.Add(4 * (i + 1) + 2);
trilist.Add(4 * (i + 1) + 3);
}
unityMesh.SetTriangles(trilist, 1);
var uvlist = new Vector2[20];
uvlist[0] = new Vector2(0, 1);
uvlist[1] = new Vector2(1, 1);
uvlist[2] = new Vector2(1, 0);
uvlist[3] = new Vector2(0, 0);
for (int i = 4; i < 20; i += 4)
{
uvlist[i] = new Vector2(1, 1);
uvlist[i + 1] = new Vector2(0, 1);
uvlist[i + 2] = new Vector2(1, 0);
uvlist[i + 3] = new Vector2(0, 0);
}
unityMesh.uv = uvlist;
_cachedQuad = new MeshDataArray()
{
Vertices = verts,
Normals = norms,
Triangles = trilist.ToArray(),
Uvs = uvlist
};
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: dc77d6f0c5be2cb49bf8014f58feeb43
timeCreated: 1522755493
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,403 @@
using System.Collections.Generic;
using UnityEngine;
using Mapbox.Unity.MeshGeneration.Data;
using Mapbox.Unity.Map;
using Mapbox.Map;
using Mapbox.Utils;
using UnityEngine.Rendering;
namespace Mapbox.Unity.MeshGeneration.Factories.TerrainStrategies
{
public class LowPolyTerrainStrategy : TerrainStrategy, IElevationBasedTerrainStrategy
{
protected Dictionary<UnwrappedTileId, Mesh> _meshData;
private Mesh _stitchTarget;
private MeshData _currentTileMeshData;
private MeshData _stitchTargetMeshData;
private List<Vector3> _newVertexList;
private List<Vector3> _newNormalList;
private List<Vector2> _newUvList;
private List<int> _newTriangleList;
private Vector3 _newDir;
private int _vertA, _vertB, _vertC;
private int _counter;
public override void Initialize(ElevationLayerProperties elOptions)
{
_elevationOptions = elOptions;
_meshData = new Dictionary<UnwrappedTileId, Mesh>();
_currentTileMeshData = new MeshData();
_stitchTargetMeshData = new MeshData();
var sampleCountSquare = _elevationOptions.modificationOptions.sampleCount * _elevationOptions.modificationOptions.sampleCount;
_newVertexList = new List<Vector3>(sampleCountSquare);
_newNormalList = new List<Vector3>(sampleCountSquare);
_newUvList = new List<Vector2>(sampleCountSquare);
_newTriangleList = new List<int>();
}
public override void UnregisterTile(UnityTile tile)
{
_meshData.Remove(tile.UnwrappedTileId);
}
public override void RegisterTile(UnityTile tile)
{
if (_elevationOptions.unityLayerOptions.addToLayer && tile.gameObject.layer != _elevationOptions.unityLayerOptions.layerId)
{
tile.gameObject.layer = _elevationOptions.unityLayerOptions.layerId;
}
if ((int)tile.ElevationType != (int)ElevationLayerType.LowPolygonTerrain ||
tile.MeshFilter.sharedMesh.vertexCount != RequiredVertexCount)
{
tile.MeshFilter.sharedMesh.Clear();
CreateBaseMesh(tile);
tile.ElevationType = TileTerrainType.LowPoly;
}
GenerateTerrainMesh(tile);
}
private void CreateBaseMesh(UnityTile tile)
{
//TODO use arrays instead of lists
_newVertexList.Clear();
_newNormalList.Clear();
_newUvList.Clear();
_newTriangleList.Clear();
var cap = (_elevationOptions.modificationOptions.sampleCount - 1);
for (float y = 0; y < cap; y++)
{
for (float x = 0; x < cap; x++)
{
var x1 = tile.TileScale * (float)(Mathd.Lerp(tile.Rect.Min.x, tile.Rect.Max.x, x / cap) - tile.Rect.Center.x);
var y1 = tile.TileScale * (float)(Mathd.Lerp(tile.Rect.Min.y, tile.Rect.Max.y, y / cap) - tile.Rect.Center.y);
var x2 = tile.TileScale * (float)(Mathd.Lerp(tile.Rect.Min.x, tile.Rect.Max.x, (x + 1) / cap) - tile.Rect.Center.x);
var y2 = tile.TileScale * (float)(Mathd.Lerp(tile.Rect.Min.y, tile.Rect.Max.y, (y + 1) / cap) - tile.Rect.Center.y);
var triStart = _newVertexList.Count;
_newVertexList.Add(new Vector3(x1, 0, y1));
_newVertexList.Add(new Vector3(x2, 0, y1));
_newVertexList.Add(new Vector3(x1, 0, y2));
//--
_newVertexList.Add(new Vector3(x2, 0, y1));
_newVertexList.Add(new Vector3(x2, 0, y2));
_newVertexList.Add(new Vector3(x1, 0, y2));
_newNormalList.Add(Mapbox.Unity.Constants.Math.Vector3Up);
_newNormalList.Add(Mapbox.Unity.Constants.Math.Vector3Up);
_newNormalList.Add(Mapbox.Unity.Constants.Math.Vector3Up);
//--
_newNormalList.Add(Mapbox.Unity.Constants.Math.Vector3Up);
_newNormalList.Add(Mapbox.Unity.Constants.Math.Vector3Up);
_newNormalList.Add(Mapbox.Unity.Constants.Math.Vector3Up);
_newUvList.Add(new Vector2(x / cap, 1 - y / cap));
_newUvList.Add(new Vector2((x + 1) / cap, 1 - y / cap));
_newUvList.Add(new Vector2(x / cap, 1 - (y + 1) / cap));
//--
_newUvList.Add(new Vector2((x + 1) / cap, 1 - y / cap));
_newUvList.Add(new Vector2((x + 1) / cap, 1 - (y + 1) / cap));
_newUvList.Add(new Vector2(x / cap, 1 - (y + 1) / cap));
_newTriangleList.Add(triStart);
_newTriangleList.Add(triStart + 1);
_newTriangleList.Add(triStart + 2);
//--
_newTriangleList.Add(triStart + 3);
_newTriangleList.Add(triStart + 4);
_newTriangleList.Add(triStart + 5);
}
}
var mesh = tile.MeshFilter.sharedMesh;
mesh.indexFormat = IndexFormat.UInt32;
mesh.SetVertices(_newVertexList);
mesh.SetNormals(_newNormalList);
mesh.SetUVs(0, _newUvList);
mesh.SetTriangles(_newTriangleList, 0);
mesh.RecalculateBounds();
}
/// <summary>
/// Creates the non-flat terrain mesh, using a grid by defined resolution (_sampleCount). Vertex order goes right & up. Normals are calculated manually and UV map is fitted/stretched 1-1.
/// Any additional scripts or logic, like MeshCollider or setting layer, can be done here.
/// </summary>
/// <param name="tile"></param>
// <param name="heightMultiplier">Multiplier for queried height value</param>
private void GenerateTerrainMesh(UnityTile tile)
{
tile.MeshFilter.sharedMesh.GetVertices(_currentTileMeshData.Vertices);
tile.MeshFilter.sharedMesh.GetNormals(_currentTileMeshData.Normals);
var cap = (_elevationOptions.modificationOptions.sampleCount - 1);
for (float y = 0; y < cap; y++)
{
for (float x = 0; x < cap; x++)
{
_currentTileMeshData.Vertices[(int)(y * cap + x) * 6] = new Vector3(
_currentTileMeshData.Vertices[(int)(y * cap + x) * 6].x,
tile.QueryHeightData(x / cap, 1 - y / cap),
_currentTileMeshData.Vertices[(int)(y * cap + x) * 6].z);
_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 1] = new Vector3(
_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 1].x,
tile.QueryHeightData((x + 1) / cap, 1 - y / cap),
_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 1].z);
_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 2] = new Vector3(
_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 2].x,
tile.QueryHeightData(x / cap, 1 - (y + 1) / cap),
_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 2].z);
//--
_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 3] = new Vector3(
_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 3].x,
tile.QueryHeightData((x + 1) / cap, 1 - y / cap),
_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 3].z);
_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 4] = new Vector3(
_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 4].x,
tile.QueryHeightData((x + 1) / cap, 1 - (y + 1) / cap),
_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 4].z);
_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 5] = new Vector3(
_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 5].x,
tile.QueryHeightData(x / cap, 1 - (y + 1) / cap),
_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 5].z);
_newDir = Vector3.Cross(_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 1] - _currentTileMeshData.Vertices[(int)(y * cap + x) * 6], _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 2] - _currentTileMeshData.Vertices[(int)(y * cap + x) * 6]);
_currentTileMeshData.Normals[(int)(y * cap + x) * 6 + 0] = _newDir;
_currentTileMeshData.Normals[(int)(y * cap + x) * 6 + 1] = _newDir;
_currentTileMeshData.Normals[(int)(y * cap + x) * 6 + 2] = _newDir;
//--
_newDir = Vector3.Cross(_currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 4] - _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 3], _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 5] - _currentTileMeshData.Vertices[(int)(y * cap + x) * 6 + 3]);
_currentTileMeshData.Normals[(int)(y * cap + x) * 6 + 3] = _newDir;
_currentTileMeshData.Normals[(int)(y * cap + x) * 6 + 4] = _newDir;
_currentTileMeshData.Normals[(int)(y * cap + x) * 6 + 5] = _newDir;
}
}
FixStitches(tile.UnwrappedTileId, _currentTileMeshData);
tile.MeshFilter.sharedMesh.SetVertices(_currentTileMeshData.Vertices);
tile.MeshFilter.sharedMesh.SetNormals(_currentTileMeshData.Normals);
tile.MeshFilter.sharedMesh.RecalculateBounds();
if (!_meshData.ContainsKey(tile.UnwrappedTileId))
{
_meshData.Add(tile.UnwrappedTileId, tile.MeshFilter.sharedMesh);
}
if (_elevationOptions.colliderOptions.addCollider)
{
var meshCollider = tile.Collider as MeshCollider;
if (meshCollider)
{
meshCollider.sharedMesh = tile.MeshFilter.sharedMesh;
}
}
}
private void ResetToFlatMesh(UnityTile tile)
{
tile.MeshFilter.sharedMesh.GetVertices(_currentTileMeshData.Vertices);
tile.MeshFilter.sharedMesh.GetNormals(_currentTileMeshData.Normals);
_counter = _currentTileMeshData.Vertices.Count;
for (int i = 0; i < _counter; i++)
{
_currentTileMeshData.Vertices[i] = new Vector3(
_currentTileMeshData.Vertices[i].x,
0,
_currentTileMeshData.Vertices[i].z);
_currentTileMeshData.Normals[i] = Mapbox.Unity.Constants.Math.Vector3Up;
}
tile.MeshFilter.sharedMesh.SetVertices(_currentTileMeshData.Vertices);
tile.MeshFilter.sharedMesh.SetNormals(_currentTileMeshData.Normals);
}
/// <summary>
/// Checkes all neighbours of the given tile and stitches the edges to achieve a smooth mesh surface.
/// </summary>
/// <param name="tileId"></param>
/// <param name="mesh"></param>
private void FixStitches(UnwrappedTileId tileId, MeshData mesh)
{
var meshVertCount = mesh.Vertices.Count;
_stitchTarget = null;
_meshData.TryGetValue(tileId.North, out _stitchTarget);
var cap = _elevationOptions.modificationOptions.sampleCount - 1;
if (_stitchTarget != null)
{
_stitchTarget.GetVertices(_stitchTargetMeshData.Vertices);
_stitchTarget.GetNormals(_stitchTargetMeshData.Normals);
for (int i = 0; i < cap; i++)
{
mesh.Vertices[6 * i] = new Vector3(
mesh.Vertices[6 * i].x,
_stitchTargetMeshData.Vertices[6 * cap * (cap - 1) + 6 * i + 2].y,
mesh.Vertices[6 * i].z);
mesh.Vertices[6 * i + 1] = new Vector3(
mesh.Vertices[6 * i + 1].x,
_stitchTargetMeshData.Vertices[6 * cap * (cap - 1) + 6 * i + 4].y,
mesh.Vertices[6 * i + 1].z);
mesh.Vertices[6 * i + 3] = new Vector3(
mesh.Vertices[6 * i + 3].x,
_stitchTargetMeshData.Vertices[6 * cap * (cap - 1) + 6 * i + 4].y,
mesh.Vertices[6 * i + 3].z);
}
}
_stitchTarget = null;
_meshData.TryGetValue(tileId.South, out _stitchTarget);
if (_stitchTarget != null)
{
_stitchTarget.GetVertices(_stitchTargetMeshData.Vertices);
_stitchTarget.GetNormals(_stitchTargetMeshData.Normals);
for (int i = 0; i < cap; i++)
{
mesh.Vertices[6 * cap * (cap - 1) + 6 * i + 2] = new Vector3(
mesh.Vertices[6 * cap * (cap - 1) + 6 * i + 2].x,
_stitchTargetMeshData.Vertices[6 * i].y,
mesh.Vertices[6 * cap * (cap - 1) + 6 * i + 2].z);
mesh.Vertices[6 * cap * (cap - 1) + 6 * i + 5] = new Vector3(
mesh.Vertices[6 * cap * (cap - 1) + 6 * i + 5].x,
_stitchTargetMeshData.Vertices[6 * i].y,
mesh.Vertices[6 * cap * (cap - 1) + 6 * i + 5].z);
mesh.Vertices[6 * cap * (cap - 1) + 6 * i + 4] = new Vector3(
mesh.Vertices[6 * cap * (cap - 1) + 6 * i + 4].x,
_stitchTargetMeshData.Vertices[6 * i + 3].y,
mesh.Vertices[6 * cap * (cap - 1) + 6 * i + 4].z);
}
}
_stitchTarget = null;
_meshData.TryGetValue(tileId.West, out _stitchTarget);
if (_stitchTarget != null)
{
_stitchTarget.GetVertices(_stitchTargetMeshData.Vertices);
_stitchTarget.GetNormals(_stitchTargetMeshData.Normals);
for (int i = 0; i < cap; i++)
{
mesh.Vertices[6 * cap * i] = new Vector3(
mesh.Vertices[6 * cap * i].x,
_stitchTargetMeshData.Vertices[6 * cap * i + 6 * cap - 5].y,
mesh.Vertices[6 * cap * i].z);
mesh.Vertices[6 * cap * i + 2] = new Vector3(
mesh.Vertices[6 * cap * i + 2].x,
_stitchTargetMeshData.Vertices[6 * cap * i + 6 * cap - 2].y,
mesh.Vertices[6 * cap * i + 2].z);
mesh.Vertices[6 * cap * i + 5] = new Vector3(
mesh.Vertices[6 * cap * i + 5].x,
_stitchTargetMeshData.Vertices[6 * cap * i + 6 * cap - 2].y,
mesh.Vertices[6 * cap * i + 5].z);
}
}
_stitchTarget = null;
_meshData.TryGetValue(tileId.East, out _stitchTarget);
if (_stitchTarget != null)
{
_stitchTarget.GetVertices(_stitchTargetMeshData.Vertices);
_stitchTarget.GetNormals(_stitchTargetMeshData.Normals);
for (int i = 0; i < cap; i++)
{
mesh.Vertices[6 * cap * i + 6 * cap - 5] = new Vector3(
mesh.Vertices[6 * cap * i + 6 * cap - 5].x,
_stitchTargetMeshData.Vertices[6 * cap * i].y,
mesh.Vertices[6 * cap * i + 6 * cap - 5].z);
mesh.Vertices[6 * cap * i + 6 * cap - 3] = new Vector3(
mesh.Vertices[6 * cap * i + 6 * cap - 3].x,
_stitchTargetMeshData.Vertices[6 * cap * i].y,
mesh.Vertices[6 * cap * i + 6 * cap - 3].z);
mesh.Vertices[6 * cap * i + 6 * cap - 2] = new Vector3(
mesh.Vertices[6 * cap * i + 6 * cap - 2].x,
_stitchTargetMeshData.Vertices[6 * cap * i + 5].y,
mesh.Vertices[6 * cap * i + 6 * cap - 2].z);
}
}
_stitchTarget = null;
_meshData.TryGetValue(tileId.NorthWest, out _stitchTarget);
if (_stitchTarget != null)
{
_stitchTarget.GetVertices(_stitchTargetMeshData.Vertices);
_stitchTarget.GetNormals(_stitchTargetMeshData.Normals);
mesh.Vertices[0] = new Vector3(
mesh.Vertices[0].x,
_stitchTargetMeshData.Vertices[meshVertCount - 2].y,
mesh.Vertices[0].z);
}
_stitchTarget = null;
_meshData.TryGetValue(tileId.NorthEast, out _stitchTarget);
if (_stitchTarget != null)
{
_stitchTarget.GetVertices(_stitchTargetMeshData.Vertices);
_stitchTarget.GetNormals(_stitchTargetMeshData.Normals);
mesh.Vertices[6 * cap - 5] = new Vector3(
mesh.Vertices[6 * cap - 5].x,
_stitchTargetMeshData.Vertices[6 * (cap - 1) * cap + 2].y,
mesh.Vertices[6 * cap - 5].z);
mesh.Vertices[6 * cap - 3] = new Vector3(
mesh.Vertices[6 * cap - 3].x,
_stitchTargetMeshData.Vertices[6 * (cap - 1) * cap + 2].y,
mesh.Vertices[6 * cap - 3].z);
}
_stitchTarget = null;
_meshData.TryGetValue(tileId.SouthWest, out _stitchTarget);
if (_stitchTarget != null)
{
_stitchTarget.GetVertices(_stitchTargetMeshData.Vertices);
_stitchTarget.GetNormals(_stitchTargetMeshData.Normals);
mesh.Vertices[6 * (cap - 1) * cap + 2] = new Vector3(
mesh.Vertices[6 * (cap - 1) * cap + 2].x,
_stitchTargetMeshData.Vertices[6 * cap - 5].y,
mesh.Vertices[6 * (cap - 1) * cap + 2].z);
mesh.Vertices[6 * (cap - 1) * cap + 5] = new Vector3(
mesh.Vertices[6 * (cap - 1) * cap + 5].x,
_stitchTargetMeshData.Vertices[6 * cap - 5].y,
mesh.Vertices[6 * (cap - 1) * cap + 5].z);
}
_stitchTarget = null;
_meshData.TryGetValue(tileId.SouthEast, out _stitchTarget);
if (_stitchTarget != null)
{
_stitchTarget.GetVertices(_stitchTargetMeshData.Vertices);
_stitchTarget.GetNormals(_stitchTargetMeshData.Normals);
mesh.Vertices[6 * cap * cap - 2] = new Vector3(
mesh.Vertices[6 * cap * cap - 2].x,
_stitchTargetMeshData.Vertices[0].y,
mesh.Vertices[6 * cap * cap - 2].z);
}
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 2e1d75acbfaded5459635c6030b0f915
timeCreated: 1522755493
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,45 @@
using UnityEngine;
using Mapbox.Unity.MeshGeneration.Data;
using System;
using Mapbox.Unity.Map;
using System.Collections.ObjectModel;
using Mapbox.Map;
namespace Mapbox.Unity.MeshGeneration.Factories.TerrainStrategies
{
public class TerrainStrategy
{
[SerializeField]
protected ElevationLayerProperties _elevationOptions = new ElevationLayerProperties();
public virtual int RequiredVertexCount
{
get { return 0; }
}
public virtual void Initialize(ElevationLayerProperties elOptions)
{
_elevationOptions = elOptions;
}
public virtual void RegisterTile(UnityTile tile)
{
}
public virtual void PostProcessTile(UnityTile tile)
{
}
public virtual void UnregisterTile(UnityTile tile)
{
}
public virtual void DataErrorOccurred(UnityTile tile, TileErrorEventArgs e)
{
}
}
}
@@ -0,0 +1,13 @@
fileFormatVersion: 2
guid: 33b4040c296ec314793ac7182cc3e81c
timeCreated: 1522755493
licenseType: Free
MonoImporter:
externalObjects: {}
serializedVersion: 2
defaultReferences: []
executionOrder: 0
icon: {instanceID: 0}
userData:
assetBundleName:
assetBundleVariant: