[TASK] Initial commit with basic product setup
This commit is contained in:
@@ -0,0 +1,140 @@
|
||||
namespace Mapbox.Unity.MeshGeneration.Factories
|
||||
{
|
||||
using Mapbox.Platform;
|
||||
using Mapbox.Unity.MeshGeneration.Data;
|
||||
using System;
|
||||
using UnityEngine;
|
||||
using Mapbox.Unity.Map;
|
||||
using Mapbox.Map;
|
||||
using System.Collections.Generic;
|
||||
|
||||
/// <summary>
|
||||
/// Factories
|
||||
/// Factories corresponds to Mapbox Api endpoints for the most part.Terrain factory uses terrain rgb api,
|
||||
/// Image factory uses raster image api and vector tile factory uses vector data api.
|
||||
/// Only exception to this at the moment is Directions factory, which is a monobehaviour in Drive demo scene
|
||||
/// but we’ll probably rework that in the future as well.
|
||||
/// Factories do the api calls.They are responsible for reporting progress and logging/reporting any network issue.
|
||||
/// They can also keep track of tiles if necessary (i.e.update/refresh data after initial creation)
|
||||
/// Factories processes the received data in different ways.
|
||||
/// Terrain factories creates the mesh from the received data (or a flat terrain depending the settings)
|
||||
/// MapImage factory applies received image to tile game object.
|
||||
/// Vector Tile Factory deals with a much more complex and detailed data compared to other two so it doesn’t do the
|
||||
/// whole processing itself and uses some subclasses (LayerVisualizers) to do it.
|
||||
/// Creating a custom factory is a good idea if you want to fetch raw data and process is in a totally different
|
||||
/// custom way, like creating terrain and then cut off water areas from terrain mesh.
|
||||
/// Vector Tile factory, for example, is built to be flexible and work with multiple vector layers. But if you
|
||||
/// don’t need that all, you can create a custom version of it and process what you need in a much more concrete
|
||||
/// and performant way.
|
||||
/// Another example here would be custom terrain mesh. Current terrain factories work with a custom sized grid
|
||||
/// and apply height data on that. By creating a custom terrain factory, you can have a custom mesh instead of a grid,
|
||||
/// optimize and minimize vertex count etc.
|
||||
/// </summary>
|
||||
public abstract class AbstractTileFactory : ScriptableObject
|
||||
{
|
||||
protected IFileSource _fileSource;
|
||||
|
||||
protected LayerProperties _options;
|
||||
public LayerProperties Options
|
||||
{
|
||||
get
|
||||
{
|
||||
return _options;
|
||||
}
|
||||
}
|
||||
|
||||
protected HashSet<UnityTile> _tilesWaitingResponse;
|
||||
protected HashSet<UnityTile> _tilesWaitingProcessing;
|
||||
|
||||
/// <summary>
|
||||
/// The <c>OnTileError</c> event triggers when there's <c>Tile</c> error.
|
||||
/// Returns a <see cref="T:Mapbox.Map.TileErrorEventArgs"/> instance as a parameter, for the tile on which error occurred.
|
||||
/// </summary>
|
||||
|
||||
public virtual void SetOptions(LayerProperties options)
|
||||
{
|
||||
_options = options;
|
||||
}
|
||||
|
||||
protected virtual void OnErrorOccurred(UnityTile tile, TileErrorEventArgs e)
|
||||
{
|
||||
EventHandler<TileErrorEventArgs> handler = OnTileError;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Initialize(IFileSource fileSource)
|
||||
{
|
||||
_fileSource = fileSource;
|
||||
_tilesWaitingResponse = new HashSet<UnityTile>();
|
||||
_tilesWaitingProcessing = new HashSet<UnityTile>();
|
||||
OnInitialized();
|
||||
}
|
||||
|
||||
public virtual void Register(UnityTile tile)
|
||||
{
|
||||
OnRegistered(tile);
|
||||
}
|
||||
|
||||
public virtual void PostProcess(UnityTile tile)
|
||||
{
|
||||
OnPostProcess(tile);
|
||||
}
|
||||
public virtual void Unregister(UnityTile tile)
|
||||
{
|
||||
OnUnregistered(tile);
|
||||
}
|
||||
|
||||
public virtual void UnbindEvents()
|
||||
{
|
||||
OnUnbindEvents();
|
||||
}
|
||||
|
||||
public virtual void UpdateTileProperty(UnityTile tile, LayerUpdateArgs updateArgs)
|
||||
{
|
||||
updateArgs.property.UpdateProperty(tile);
|
||||
|
||||
if (updateArgs.property.NeedsForceUpdate())
|
||||
{
|
||||
Register(tile);
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void Reset()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
protected abstract void OnInitialized();
|
||||
|
||||
protected abstract void OnRegistered(UnityTile tile);
|
||||
protected abstract void OnPostProcess(UnityTile tile);
|
||||
protected abstract void OnUnregistered(UnityTile tile);
|
||||
protected abstract void OnUnbindEvents();
|
||||
|
||||
#region Events
|
||||
public event EventHandler<TileErrorEventArgs> OnTileError;
|
||||
protected virtual void OnErrorOccurred(TileErrorEventArgs e)
|
||||
{
|
||||
EventHandler<TileErrorEventArgs> handler = OnTileError;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, e);
|
||||
}
|
||||
}
|
||||
|
||||
public event EventHandler TileFactoryHasChanged;
|
||||
protected virtual void UpdateTileFactory(object sender, System.EventArgs args)
|
||||
{
|
||||
System.EventHandler handler = TileFactoryHasChanged;
|
||||
if (handler != null)
|
||||
{
|
||||
handler(this, args);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14c4d9b107de24a028e1bd452df7ae29
|
||||
timeCreated: 1494972519
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,165 @@
|
||||
namespace Mapbox.Unity.MeshGeneration.Factories
|
||||
{
|
||||
using UnityEngine;
|
||||
using Mapbox.Directions;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Mapbox.Unity.Map;
|
||||
using Data;
|
||||
using Modifiers;
|
||||
using Mapbox.Utils;
|
||||
using Mapbox.Unity.Utilities;
|
||||
using System.Collections;
|
||||
|
||||
public class DirectionsFactory : MonoBehaviour
|
||||
{
|
||||
[SerializeField]
|
||||
AbstractMap _map;
|
||||
|
||||
[SerializeField]
|
||||
MeshModifier[] MeshModifiers;
|
||||
[SerializeField]
|
||||
Material _material;
|
||||
|
||||
[SerializeField]
|
||||
Transform[] _waypoints;
|
||||
private List<Vector3> _cachedWaypoints;
|
||||
|
||||
[SerializeField]
|
||||
[Range(1,10)]
|
||||
private float UpdateFrequency = 2;
|
||||
|
||||
|
||||
|
||||
private Directions _directions;
|
||||
private int _counter;
|
||||
|
||||
GameObject _directionsGO;
|
||||
private bool _recalculateNext;
|
||||
|
||||
protected virtual void Awake()
|
||||
{
|
||||
if (_map == null)
|
||||
{
|
||||
_map = FindObjectOfType<AbstractMap>();
|
||||
}
|
||||
_directions = MapboxAccess.Instance.Directions;
|
||||
_map.OnInitialized += Query;
|
||||
_map.OnUpdated += Query;
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
_cachedWaypoints = new List<Vector3>(_waypoints.Length);
|
||||
foreach (var item in _waypoints)
|
||||
{
|
||||
_cachedWaypoints.Add(item.position);
|
||||
}
|
||||
_recalculateNext = false;
|
||||
|
||||
foreach (var modifier in MeshModifiers)
|
||||
{
|
||||
modifier.Initialize();
|
||||
}
|
||||
|
||||
StartCoroutine(QueryTimer());
|
||||
}
|
||||
|
||||
protected virtual void OnDestroy()
|
||||
{
|
||||
_map.OnInitialized -= Query;
|
||||
_map.OnUpdated -= Query;
|
||||
}
|
||||
|
||||
void Query()
|
||||
{
|
||||
var count = _waypoints.Length;
|
||||
var wp = new Vector2d[count];
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
wp[i] = _waypoints[i].GetGeoPosition(_map.CenterMercator, _map.WorldRelativeScale);
|
||||
}
|
||||
var _directionResource = new DirectionResource(wp, RoutingProfile.Driving);
|
||||
_directionResource.Steps = true;
|
||||
_directions.Query(_directionResource, HandleDirectionsResponse);
|
||||
}
|
||||
|
||||
public IEnumerator QueryTimer()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
yield return new WaitForSeconds(UpdateFrequency);
|
||||
for (int i = 0; i < _waypoints.Length; i++)
|
||||
{
|
||||
if (_waypoints[i].position != _cachedWaypoints[i])
|
||||
{
|
||||
_recalculateNext = true;
|
||||
_cachedWaypoints[i] = _waypoints[i].position;
|
||||
}
|
||||
}
|
||||
|
||||
if (_recalculateNext)
|
||||
{
|
||||
Query();
|
||||
_recalculateNext = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void HandleDirectionsResponse(DirectionsResponse response)
|
||||
{
|
||||
if (response == null || null == response.Routes || response.Routes.Count < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var meshData = new MeshData();
|
||||
var dat = new List<Vector3>();
|
||||
foreach (var point in response.Routes[0].Geometry)
|
||||
{
|
||||
dat.Add(Conversions.GeoToWorldPosition(point.x, point.y, _map.CenterMercator, _map.WorldRelativeScale).ToVector3xz());
|
||||
}
|
||||
|
||||
var feat = new VectorFeatureUnity();
|
||||
feat.Points.Add(dat);
|
||||
|
||||
foreach (MeshModifier mod in MeshModifiers.Where(x => x.Active))
|
||||
{
|
||||
mod.Run(feat, meshData, _map.WorldRelativeScale);
|
||||
}
|
||||
|
||||
CreateGameObject(meshData);
|
||||
}
|
||||
|
||||
GameObject CreateGameObject(MeshData data)
|
||||
{
|
||||
if (_directionsGO != null)
|
||||
{
|
||||
Destroy(_directionsGO);
|
||||
}
|
||||
_directionsGO = new GameObject("direction waypoint " + " entity");
|
||||
var mesh = _directionsGO.AddComponent<MeshFilter>().mesh;
|
||||
mesh.subMeshCount = data.Triangles.Count;
|
||||
|
||||
mesh.SetVertices(data.Vertices);
|
||||
_counter = data.Triangles.Count;
|
||||
for (int i = 0; i < _counter; i++)
|
||||
{
|
||||
var triangle = data.Triangles[i];
|
||||
mesh.SetTriangles(triangle, i);
|
||||
}
|
||||
|
||||
_counter = data.UV.Count;
|
||||
for (int i = 0; i < _counter; i++)
|
||||
{
|
||||
var uv = data.UV[i];
|
||||
mesh.SetUVs(i, uv);
|
||||
}
|
||||
|
||||
mesh.RecalculateNormals();
|
||||
_directionsGO.AddComponent<MeshRenderer>().material = _material;
|
||||
return _directionsGO;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 44d601772d842a94cb5ab933dca6bd4f
|
||||
timeCreated: 1485217963
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,54 @@
|
||||
using Mapbox.Map;
|
||||
using Mapbox.Unity.MeshGeneration.Data;
|
||||
using Mapbox.Unity.MeshGeneration.Enums;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public class ImageDataFetcher : DataFetcher
|
||||
{
|
||||
public Action<UnityTile, RasterTile> DataRecieved = (t, s) => { };
|
||||
public Action<UnityTile, RasterTile, TileErrorEventArgs> FetchingError = (t, r, s) => { };
|
||||
|
||||
//tile here should be totally optional and used only not to have keep a dictionary in terrain factory base
|
||||
public override void FetchData(DataFetcherParameters parameters)
|
||||
{
|
||||
var imageDataParameters = parameters as ImageDataFetcherParameters;
|
||||
if(imageDataParameters == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
RasterTile rasterTile;
|
||||
if (imageDataParameters.mapid.StartsWith("mapbox://", StringComparison.Ordinal))
|
||||
{
|
||||
rasterTile = imageDataParameters.useRetina ? new RetinaRasterTile() : new RasterTile();
|
||||
}
|
||||
else
|
||||
{
|
||||
rasterTile = imageDataParameters.useRetina ? new ClassicRetinaRasterTile() : new ClassicRasterTile();
|
||||
}
|
||||
|
||||
if (imageDataParameters.tile != null)
|
||||
{
|
||||
imageDataParameters.tile.AddTile(rasterTile);
|
||||
}
|
||||
|
||||
rasterTile.Initialize(_fileSource, imageDataParameters.tile.CanonicalTileId, imageDataParameters.mapid, () =>
|
||||
{
|
||||
if (imageDataParameters.tile.CanonicalTileId != rasterTile.Id)
|
||||
{
|
||||
//this means tile object is recycled and reused. Returned data doesn't belong to this tile but probably the previous one. So we're trashing it.
|
||||
return;
|
||||
}
|
||||
|
||||
if (rasterTile.HasError)
|
||||
{
|
||||
FetchingError(imageDataParameters.tile, rasterTile, new TileErrorEventArgs(imageDataParameters.tile.CanonicalTileId, rasterTile.GetType(), imageDataParameters.tile, rasterTile.Exceptions));
|
||||
}
|
||||
else
|
||||
{
|
||||
DataRecieved(imageDataParameters.tile, rasterTile);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6293dc8bcca4970409cf9f4e93d178b5
|
||||
timeCreated: 1524268181
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,166 @@
|
||||
namespace Mapbox.Unity.MeshGeneration.Factories
|
||||
{
|
||||
using System;
|
||||
using Mapbox.Map;
|
||||
using UnityEngine;
|
||||
using Mapbox.Unity.MeshGeneration.Enums;
|
||||
using Mapbox.Unity.MeshGeneration.Data;
|
||||
using Mapbox.Unity.Utilities;
|
||||
using Mapbox.Unity.Map;
|
||||
using System.Collections.Generic;
|
||||
|
||||
public enum MapImageType
|
||||
{
|
||||
BasicMapboxStyle,
|
||||
Custom,
|
||||
None
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Uses raster image services to create materials & textures for terrain
|
||||
/// </summary>
|
||||
[CreateAssetMenu(menuName = "Mapbox/Factories/Image Factory")]
|
||||
public class MapImageFactory : AbstractTileFactory
|
||||
{
|
||||
[SerializeField]
|
||||
ImageryLayerProperties _properties;
|
||||
protected ImageDataFetcher DataFetcher;
|
||||
|
||||
public ImageryLayerProperties Properties
|
||||
{
|
||||
get
|
||||
{
|
||||
return _properties;
|
||||
}
|
||||
}
|
||||
|
||||
public string MapId
|
||||
{
|
||||
get
|
||||
{
|
||||
return _properties.sourceOptions.Id;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_properties.sourceOptions.Id = value;
|
||||
}
|
||||
}
|
||||
|
||||
#region UnityMethods
|
||||
protected virtual void OnDestroy()
|
||||
{
|
||||
//unregister events
|
||||
if (DataFetcher != null)
|
||||
{
|
||||
DataFetcher.DataRecieved -= OnImageRecieved;
|
||||
DataFetcher.FetchingError -= OnDataError;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region DataFetcherEvents
|
||||
private void OnImageRecieved(UnityTile tile, RasterTile rasterTile)
|
||||
{
|
||||
if (tile != null)
|
||||
{
|
||||
if (tile.RasterDataState != TilePropertyState.Unregistered)
|
||||
{
|
||||
_tilesWaitingResponse.Remove(tile);
|
||||
tile.SetRasterData(rasterTile.Data, _properties.rasterOptions.useMipMap, _properties.rasterOptions.useCompression);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//merge this with OnErrorOccurred?
|
||||
protected virtual void OnDataError(UnityTile tile, RasterTile rasterTile, TileErrorEventArgs e)
|
||||
{
|
||||
if (tile != null)
|
||||
{
|
||||
if (tile.RasterDataState != TilePropertyState.Unregistered)
|
||||
{
|
||||
tile.RasterDataState = TilePropertyState.Error;
|
||||
_tilesWaitingResponse.Remove(tile);
|
||||
OnErrorOccurred(e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AbstractFactoryOverrides
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
DataFetcher = ScriptableObject.CreateInstance<ImageDataFetcher>();
|
||||
DataFetcher.DataRecieved += OnImageRecieved;
|
||||
DataFetcher.FetchingError += OnDataError;
|
||||
}
|
||||
|
||||
public override void SetOptions(LayerProperties options)
|
||||
{
|
||||
_properties = (ImageryLayerProperties)options;
|
||||
}
|
||||
|
||||
protected override void OnRegistered(UnityTile tile)
|
||||
{
|
||||
if (_properties.sourceType == ImagerySourceType.None)
|
||||
{
|
||||
tile.SetRasterData(null);
|
||||
tile.RasterDataState = TilePropertyState.None;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
tile.RasterDataState = TilePropertyState.Loading;
|
||||
if (_properties.sourceType != ImagerySourceType.Custom)
|
||||
{
|
||||
_properties.sourceOptions.layerSource = MapboxDefaultImagery.GetParameters(_properties.sourceType);
|
||||
}
|
||||
ImageDataFetcherParameters parameters = new ImageDataFetcherParameters()
|
||||
{
|
||||
canonicalTileId = tile.CanonicalTileId,
|
||||
tile = tile,
|
||||
mapid = MapId,
|
||||
useRetina = _properties.rasterOptions.useRetina
|
||||
};
|
||||
DataFetcher.FetchData(parameters);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method to be called when a tile error has occurred.
|
||||
/// </summary>
|
||||
/// <param name="e"><see cref="T:Mapbox.Map.TileErrorEventArgs"/> instance/</param>
|
||||
protected override void OnErrorOccurred(UnityTile tile, TileErrorEventArgs e)
|
||||
{
|
||||
base.OnErrorOccurred(tile, e);
|
||||
if (tile != null)
|
||||
{
|
||||
tile.RasterDataState = TilePropertyState.Error;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnUnregistered(UnityTile tile)
|
||||
{
|
||||
if (_tilesWaitingResponse != null && _tilesWaitingResponse.Contains(tile))
|
||||
{
|
||||
_tilesWaitingResponse.Remove(tile);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnPostProcess(UnityTile tile)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void UnbindEvents()
|
||||
{
|
||||
base.UnbindEvents();
|
||||
}
|
||||
|
||||
protected override void OnUnbindEvents()
|
||||
{
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2b10536479dade041b6db9893fdf723a
|
||||
timeCreated: 1481718773
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {fileID: 2800000, guid: 2ac69ccfbca692443a02f68e1a689694, type: 3}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,77 @@
|
||||
using Mapbox.Map;
|
||||
using Mapbox.Unity;
|
||||
using Mapbox.Unity.Map;
|
||||
using Mapbox.Unity.MeshGeneration.Data;
|
||||
using Mapbox.Unity.MeshGeneration.Enums;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
|
||||
public class DataFetcherParameters
|
||||
{
|
||||
public CanonicalTileId canonicalTileId;
|
||||
public string mapid;
|
||||
public UnityTile tile;
|
||||
}
|
||||
|
||||
public class ImageDataFetcherParameters : DataFetcherParameters
|
||||
{
|
||||
public bool useRetina = true;
|
||||
}
|
||||
|
||||
public class TerrainDataFetcherParameters : DataFetcherParameters
|
||||
{
|
||||
}
|
||||
|
||||
public class VectorDataFetcherParameters : DataFetcherParameters
|
||||
{
|
||||
public bool useOptimizedStyle = false;
|
||||
public Style style = null;
|
||||
}
|
||||
|
||||
public abstract class DataFetcher : ScriptableObject
|
||||
{
|
||||
protected MapboxAccess _fileSource;
|
||||
|
||||
public void OnEnable()
|
||||
{
|
||||
_fileSource = MapboxAccess.Instance;
|
||||
}
|
||||
|
||||
public abstract void FetchData(DataFetcherParameters parameters);
|
||||
}
|
||||
|
||||
public class TerrainDataFetcher : DataFetcher
|
||||
{
|
||||
public Action<UnityTile, RawPngRasterTile> DataRecieved = (t, s) => { };
|
||||
public Action<UnityTile, RawPngRasterTile, TileErrorEventArgs> FetchingError = (t, r, s) => { };
|
||||
|
||||
//tile here should be totally optional and used only not to have keep a dictionary in terrain factory base
|
||||
public override void FetchData(DataFetcherParameters parameters)
|
||||
{
|
||||
var terrainDataParameters = parameters as TerrainDataFetcherParameters;
|
||||
if(terrainDataParameters == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var pngRasterTile = new RawPngRasterTile();
|
||||
pngRasterTile.Initialize(_fileSource, terrainDataParameters.canonicalTileId, terrainDataParameters.mapid, () =>
|
||||
{
|
||||
if (terrainDataParameters.tile.CanonicalTileId != pngRasterTile.Id)
|
||||
{
|
||||
//this means tile object is recycled and reused. Returned data doesn't belong to this tile but probably the previous one. So we're trashing it.
|
||||
return;
|
||||
}
|
||||
|
||||
if (pngRasterTile.HasError)
|
||||
{
|
||||
FetchingError(terrainDataParameters.tile, pngRasterTile, new TileErrorEventArgs(terrainDataParameters.canonicalTileId, pngRasterTile.GetType(), null, pngRasterTile.Exceptions));
|
||||
}
|
||||
else
|
||||
{
|
||||
DataRecieved(terrainDataParameters.tile, pngRasterTile);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c823321064d5b2f4db21c4fdbd6b1c1f
|
||||
timeCreated: 1523880895
|
||||
licenseType: Free
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,170 @@
|
||||
using Mapbox.Unity.MeshGeneration.Factories;
|
||||
using System.Collections;
|
||||
using UnityEngine;
|
||||
using Mapbox.Unity.MeshGeneration.Data;
|
||||
using Mapbox.Unity.Map;
|
||||
using Mapbox.Map;
|
||||
using Mapbox.Unity.MeshGeneration.Enums;
|
||||
using Mapbox.Unity.MeshGeneration.Factories.TerrainStrategies;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Mapbox.Unity.MeshGeneration.Factories
|
||||
{
|
||||
public class TerrainFactoryBase : AbstractTileFactory
|
||||
{
|
||||
public TerrainStrategy Strategy;
|
||||
[SerializeField]
|
||||
protected ElevationLayerProperties _elevationOptions = new ElevationLayerProperties();
|
||||
protected TerrainDataFetcher DataFetcher;
|
||||
|
||||
public TerrainDataFetcher GetFetcher()
|
||||
{
|
||||
return DataFetcher;
|
||||
}
|
||||
|
||||
public ElevationLayerProperties Properties
|
||||
{
|
||||
get
|
||||
{
|
||||
return _elevationOptions;
|
||||
}
|
||||
}
|
||||
|
||||
#region UnityMethods
|
||||
private void OnDestroy()
|
||||
{
|
||||
if (DataFetcher != null)
|
||||
{
|
||||
DataFetcher.DataRecieved -= OnTerrainRecieved;
|
||||
DataFetcher.FetchingError -= OnDataError;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AbstractFactoryOverrides
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
Strategy.Initialize(_elevationOptions);
|
||||
DataFetcher = ScriptableObject.CreateInstance<TerrainDataFetcher>();
|
||||
DataFetcher.DataRecieved += OnTerrainRecieved;
|
||||
DataFetcher.FetchingError += OnDataError;
|
||||
}
|
||||
|
||||
public override void SetOptions(LayerProperties options)
|
||||
{
|
||||
_elevationOptions = (ElevationLayerProperties)options;
|
||||
Strategy.Initialize(_elevationOptions);
|
||||
}
|
||||
|
||||
protected override void OnRegistered(UnityTile tile)
|
||||
{
|
||||
if (Properties.sourceType == ElevationSourceType.None)
|
||||
{
|
||||
tile.SetHeightData(null);
|
||||
tile.MeshFilter.mesh.Clear();
|
||||
tile.ElevationType = TileTerrainType.None;
|
||||
return;
|
||||
}
|
||||
|
||||
if (Strategy is IElevationBasedTerrainStrategy)
|
||||
{
|
||||
tile.HeightDataState = TilePropertyState.Loading;
|
||||
TerrainDataFetcherParameters parameters = new TerrainDataFetcherParameters()
|
||||
{
|
||||
canonicalTileId = tile.CanonicalTileId,
|
||||
mapid = _elevationOptions.sourceOptions.Id,
|
||||
tile = tile
|
||||
};
|
||||
DataFetcher.FetchData(parameters);
|
||||
}
|
||||
else
|
||||
{
|
||||
//reseting height data
|
||||
tile.SetHeightData(null);
|
||||
Strategy.RegisterTile(tile);
|
||||
tile.HeightDataState = TilePropertyState.Loaded;
|
||||
}
|
||||
}
|
||||
|
||||
protected override void OnUnregistered(UnityTile tile)
|
||||
{
|
||||
if (_tilesWaitingResponse != null && _tilesWaitingResponse.Contains(tile))
|
||||
{
|
||||
_tilesWaitingResponse.Remove(tile);
|
||||
}
|
||||
Strategy.UnregisterTile(tile);
|
||||
}
|
||||
|
||||
protected override void OnPostProcess(UnityTile tile)
|
||||
{
|
||||
Strategy.PostProcessTile(tile);
|
||||
}
|
||||
|
||||
public override void UnbindEvents()
|
||||
{
|
||||
base.UnbindEvents();
|
||||
}
|
||||
|
||||
protected override void OnUnbindEvents()
|
||||
{
|
||||
}
|
||||
//public override void UpdateTileProperty(UnityTile tile, LayerUpdateArgs updateArgs)
|
||||
//{
|
||||
// updateArgs.property.UpdateProperty(tile);
|
||||
|
||||
// if (updateArgs.property.NeedsForceUpdate())
|
||||
// {
|
||||
// Register(tile);
|
||||
// }
|
||||
|
||||
// //if (updateArgs.property is TerrainColliderOptions)
|
||||
// //{
|
||||
// // var existingCollider = tileBundleValue.Collider;
|
||||
// // if (Properties.colliderOptions.addCollider)
|
||||
// // {
|
||||
// // if (existingCollider == null)
|
||||
// // {
|
||||
// // tileBundleValue.gameObject.AddComponent<MeshCollider>();
|
||||
// // }
|
||||
// // }
|
||||
// // else
|
||||
// // {
|
||||
// // Destroy(tileBundleValue.Collider);
|
||||
// // }
|
||||
// //}
|
||||
//}
|
||||
|
||||
#endregion
|
||||
|
||||
#region DataFetcherEvents
|
||||
private void OnTerrainRecieved(UnityTile tile, RawPngRasterTile pngRasterTile)
|
||||
{
|
||||
if (tile != null)
|
||||
{
|
||||
_tilesWaitingResponse.Remove(tile);
|
||||
if (tile.HeightDataState != TilePropertyState.Unregistered)
|
||||
{
|
||||
tile.SetHeightData(pngRasterTile.Data, _elevationOptions.requiredOptions.exaggerationFactor, _elevationOptions.modificationOptions.useRelativeHeight, _elevationOptions.colliderOptions.addCollider);
|
||||
Strategy.RegisterTile(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDataError(UnityTile tile, RawPngRasterTile rawTile, TileErrorEventArgs e)
|
||||
{
|
||||
base.OnErrorOccurred(tile, e);
|
||||
if (tile != null)
|
||||
{
|
||||
_tilesWaitingResponse.Remove(tile);
|
||||
if (tile.HeightDataState != TilePropertyState.Unregistered)
|
||||
{
|
||||
Strategy.DataErrorOccurred(tile, e);
|
||||
tile.HeightDataState = TilePropertyState.Error;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af9867f09d360f2409d9d08a0ff16906
|
||||
timeCreated: 1522684959
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 9a7ab3f3c54be5140aecaed29e7e4f65
|
||||
folderAsset: yes
|
||||
timeCreated: 1522755730
|
||||
licenseType: Free
|
||||
DefaultImporter:
|
||||
externalObjects: {}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,401 @@
|
||||
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 ElevatedTerrainStrategy : 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; }
|
||||
}
|
||||
|
||||
public override void Initialize(ElevationLayerProperties elOptions)
|
||||
{
|
||||
base.Initialize(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 ((int)tile.ElevationType != (int)ElevationLayerType.TerrainWithElevation ||
|
||||
tile.MeshFilter.mesh.vertexCount != RequiredVertexCount)
|
||||
{
|
||||
tile.MeshFilter.mesh.Clear();
|
||||
CreateBaseMesh(tile);
|
||||
tile.ElevationType = TileTerrainType.Elevated;
|
||||
}
|
||||
|
||||
GenerateTerrainMesh(tile);
|
||||
}
|
||||
|
||||
public override void UnregisterTile(UnityTile tile)
|
||||
{
|
||||
_meshData.Remove(tile.UnwrappedTileId);
|
||||
}
|
||||
|
||||
public override void DataErrorOccurred(UnityTile t, TileErrorEventArgs e)
|
||||
{
|
||||
ResetToFlatMesh(t);
|
||||
}
|
||||
|
||||
public override void PostProcessTile(UnityTile tile)
|
||||
{
|
||||
//if (_meshData.ContainsKey(tile.UnwrappedTileId))
|
||||
//{
|
||||
// FixStitches(tile.UnwrappedTileId, _meshData[tile.UnwrappedTileId]);
|
||||
// tile.MeshFilter.mesh.RecalculateBounds();
|
||||
//}
|
||||
}
|
||||
#region mesh gen
|
||||
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 mesh = tile.MeshFilter.mesh;
|
||||
mesh.SetVertices(_newVertexList);
|
||||
mesh.SetNormals(_newNormalList);
|
||||
mesh.SetUVs(0, _newUvList);
|
||||
mesh.SetTriangles(_newTriangleList, 0);
|
||||
}
|
||||
|
||||
private void GenerateTerrainMesh(UnityTile tile)
|
||||
{
|
||||
tile.MeshFilter.mesh.GetVertices(_currentTileMeshData.Vertices);
|
||||
tile.MeshFilter.mesh.GetNormals(_currentTileMeshData.Normals);
|
||||
|
||||
var _sampleCount = _elevationOptions.modificationOptions.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;
|
||||
}
|
||||
}
|
||||
|
||||
tile.MeshFilter.mesh.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.mesh.SetNormals(_currentTileMeshData.Normals);
|
||||
tile.MeshFilter.mesh.SetVertices(_currentTileMeshData.Vertices);
|
||||
|
||||
tile.MeshFilter.mesh.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.mesh.vertexCount == 0)
|
||||
{
|
||||
CreateBaseMesh(tile);
|
||||
}
|
||||
else
|
||||
{
|
||||
tile.MeshFilter.mesh.GetVertices(_currentTileMeshData.Vertices);
|
||||
tile.MeshFilter.mesh.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.mesh.SetVertices(_currentTileMeshData.Vertices);
|
||||
tile.MeshFilter.mesh.SetNormals(_currentTileMeshData.Normals);
|
||||
|
||||
tile.MeshFilter.mesh.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, MeshData mesh)
|
||||
{
|
||||
var _sampleCount = _elevationOptions.modificationOptions.sampleCount;
|
||||
var meshVertCount = mesh.Vertices.Count;
|
||||
_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.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.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.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.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);
|
||||
}
|
||||
}
|
||||
#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.mesh.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.mesh.GetVertices(_currentTileMeshData.Vertices);
|
||||
tile.MeshFilter.mesh.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.mesh.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.mesh.SetNormals(_currentTileMeshData.Normals);
|
||||
tile.MeshFilter.mesh.SetVertices(_currentTileMeshData.Vertices);
|
||||
|
||||
tile.MeshFilter.mesh.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.mesh.vertexCount == 0)
|
||||
{
|
||||
CreateBaseMesh(tile);
|
||||
}
|
||||
else
|
||||
{
|
||||
tile.MeshFilter.mesh.GetVertices(_currentTileMeshData.Vertices);
|
||||
tile.MeshFilter.mesh.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.mesh.SetVertices(_currentTileMeshData.Vertices);
|
||||
tile.MeshFilter.mesh.SetNormals(_currentTileMeshData.Normals);
|
||||
|
||||
tile.MeshFilter.mesh.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.mesh.vertexCount != RequiredVertexCount)
|
||||
{
|
||||
tile.MeshFilter.mesh.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.mesh.SetVertices(verts);
|
||||
tile.MeshFilter.mesh.SetTriangles(trilist, 0);
|
||||
tile.MeshFilter.mesh.SetUVs(0, uvlist);
|
||||
tile.MeshFilter.mesh.RecalculateBounds();
|
||||
tile.MeshFilter.mesh.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,168 @@
|
||||
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
|
||||
{
|
||||
Mesh _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.mesh.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.mesh.Clear();
|
||||
// HACK: This is here in to make the system trigger a finished state.
|
||||
tile.MeshFilter.sharedMesh = GetQuad(tile, _elevationOptions.sideWallOptions.isActive);
|
||||
tile.ElevationType = TileTerrainType.Flat;
|
||||
}
|
||||
}
|
||||
|
||||
private Mesh GetQuad(UnityTile tile, bool buildSide)
|
||||
{
|
||||
if (_cachedQuad != null)
|
||||
{
|
||||
return _cachedQuad;
|
||||
}
|
||||
|
||||
return buildSide ? BuildQuadWithSides(tile) : BuildQuad(tile);
|
||||
}
|
||||
|
||||
Mesh BuildQuad(UnityTile tile)
|
||||
{
|
||||
var unityMesh = new Mesh();
|
||||
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.SetTriangles(trilist, 0);
|
||||
|
||||
var uvlist = new Vector2[4]
|
||||
{
|
||||
new Vector2(0,1),
|
||||
new Vector2(1,1),
|
||||
new Vector2(1,0),
|
||||
new Vector2(0,0)
|
||||
};
|
||||
unityMesh.uv = uvlist;
|
||||
tile.MeshFilter.sharedMesh = unityMesh;
|
||||
_cachedQuad = unityMesh;
|
||||
|
||||
return unityMesh;
|
||||
}
|
||||
|
||||
private Mesh BuildQuadWithSides(UnityTile tile)
|
||||
{
|
||||
var unityMesh = new Mesh();
|
||||
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;
|
||||
tile.MeshFilter.sharedMesh = unityMesh;
|
||||
_cachedQuad = unityMesh;
|
||||
|
||||
return unityMesh;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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.mesh.vertexCount != RequiredVertexCount)
|
||||
{
|
||||
tile.MeshFilter.mesh.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.mesh;
|
||||
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.mesh.GetVertices(_currentTileMeshData.Vertices);
|
||||
tile.MeshFilter.mesh.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.mesh.SetVertices(_currentTileMeshData.Vertices);
|
||||
tile.MeshFilter.mesh.SetNormals(_currentTileMeshData.Normals);
|
||||
tile.MeshFilter.mesh.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)
|
||||
{
|
||||
tile.MeshFilter.mesh.GetVertices(_currentTileMeshData.Vertices);
|
||||
tile.MeshFilter.mesh.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.mesh.SetVertices(_currentTileMeshData.Vertices);
|
||||
tile.MeshFilter.mesh.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:
|
||||
@@ -0,0 +1,17 @@
|
||||
namespace Mapbox.Unity.MeshGeneration.Factories
|
||||
{
|
||||
using Mapbox.Unity.MeshGeneration.Data;
|
||||
using System;
|
||||
|
||||
public class TileProcessFinishedEventArgs : EventArgs
|
||||
{
|
||||
public AbstractTileFactory Factory;
|
||||
public UnityTile Tile;
|
||||
|
||||
public TileProcessFinishedEventArgs(AbstractTileFactory vectorTileFactory, UnityTile tile)
|
||||
{
|
||||
Factory = vectorTileFactory;
|
||||
Tile = tile;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 2e9e504493544ff4baa22317cd678f87
|
||||
timeCreated: 1532126963
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,38 @@
|
||||
using Mapbox.Map;
|
||||
using Mapbox.Unity.Map;
|
||||
using Mapbox.Unity.MeshGeneration.Data;
|
||||
using Mapbox.Unity.MeshGeneration.Enums;
|
||||
using System;
|
||||
public class VectorDataFetcher : DataFetcher
|
||||
{
|
||||
public Action<UnityTile, VectorTile> DataRecieved = (t, s) => { };
|
||||
public Action<UnityTile, VectorTile, TileErrorEventArgs> FetchingError = (t, r, s) => { };
|
||||
|
||||
//tile here should be totally optional and used only not to have keep a dictionary in terrain factory base
|
||||
public override void FetchData(DataFetcherParameters parameters)
|
||||
{
|
||||
var vectorDaraParameters = parameters as VectorDataFetcherParameters;
|
||||
if(vectorDaraParameters == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
var vectorTile = (vectorDaraParameters.useOptimizedStyle) ? new VectorTile(vectorDaraParameters.style.Id, vectorDaraParameters.style.Modified) : new VectorTile();
|
||||
vectorDaraParameters.tile.AddTile(vectorTile);
|
||||
vectorTile.Initialize(_fileSource, vectorDaraParameters.tile.CanonicalTileId, vectorDaraParameters.mapid, () =>
|
||||
{
|
||||
if (vectorDaraParameters.tile.CanonicalTileId != vectorTile.Id)
|
||||
{
|
||||
//this means tile object is recycled and reused. Returned data doesn't belong to this tile but probably the previous one. So we're trashing it.
|
||||
return;
|
||||
}
|
||||
if (vectorTile.HasError)
|
||||
{
|
||||
FetchingError(vectorDaraParameters.tile, vectorTile, new TileErrorEventArgs(vectorDaraParameters.tile.CanonicalTileId, vectorTile.GetType(), vectorDaraParameters.tile, vectorTile.Exceptions));
|
||||
}
|
||||
else
|
||||
{
|
||||
DataRecieved(vectorDaraParameters.tile, vectorTile);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b666b1dbd8d5d6444a8fc9945c0106ce
|
||||
timeCreated: 1524487271
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
@@ -0,0 +1,475 @@
|
||||
using System.Collections.Generic;
|
||||
using UnityEngine;
|
||||
using Mapbox.Unity.MeshGeneration.Enums;
|
||||
using Mapbox.Unity.MeshGeneration.Data;
|
||||
using Mapbox.Unity.MeshGeneration.Interfaces;
|
||||
using Mapbox.Map;
|
||||
using Mapbox.Unity.Map;
|
||||
using System;
|
||||
|
||||
namespace Mapbox.Unity.MeshGeneration.Factories
|
||||
{
|
||||
/// <summary>
|
||||
/// Vector Tile Factory
|
||||
/// Vector data is much more detailed compared to terrain and image data so we have a different structure to process
|
||||
/// vector data(compared to other factories). First of all, how does the vector data itself structured? Vector tile
|
||||
/// data contains 'vector layers' as immediate children.And then each of these vector layers contains a number of
|
||||
/// 'features' inside.I.e.vector data for a tile has 'building', 'road', 'landuse' etc layers. Then building layer
|
||||
/// has a number of polygon features, road layer has line features etc.
|
||||
/// Similar to this, vector tile factory contains bunch of 'layer visualizers' and each one of them corresponds to
|
||||
/// one (or more) vector layers in data.So when data is received, factory goes through all layers inside and passes
|
||||
/// them to designated layer visualizers.We're using layer name as key here, to find the designated layer visualizer,
|
||||
/// like 'building', 'road'. (vector tile factory visual would help here). If it can't find a layer visualizer for
|
||||
/// that layer, it'll be skipped and not processed at all.If all you need is 1-2 layers, it's indeed a big waste to
|
||||
/// pull whole vector data and you can use 'Style Optimized Vector Tile Factory' to pull only the layer you want to use.
|
||||
/// </summary>
|
||||
//[CreateAssetMenu(menuName = "Mapbox/Factories/Vector Tile Factory")]
|
||||
public class VectorTileFactory : AbstractTileFactory
|
||||
{
|
||||
#region Private/Protected Fields
|
||||
private Dictionary<string, List<LayerVisualizerBase>> _layerBuilder;
|
||||
private VectorLayerProperties _properties;
|
||||
private Dictionary<UnityTile, HashSet<LayerVisualizerBase>> _layerProgress;
|
||||
protected VectorDataFetcher DataFetcher;
|
||||
#endregion
|
||||
|
||||
#region Properties
|
||||
public string MapId
|
||||
{
|
||||
get
|
||||
{
|
||||
return _properties.sourceOptions.Id;
|
||||
}
|
||||
|
||||
set
|
||||
{
|
||||
_properties.sourceOptions.Id = value;
|
||||
}
|
||||
}
|
||||
|
||||
public VectorLayerProperties Properties
|
||||
{
|
||||
get
|
||||
{
|
||||
return _properties;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Methods
|
||||
public void RedrawSubLayer(UnityTile tile, LayerVisualizerBase visualizer)
|
||||
{
|
||||
CreateFeatureWithBuilder(tile, visualizer.SubLayerProperties.coreOptions.layerName, visualizer);
|
||||
}
|
||||
|
||||
public void UnregisterLayer(UnityTile tile, LayerVisualizerBase visualizer)
|
||||
{
|
||||
if (_layerProgress.ContainsKey(tile))
|
||||
{
|
||||
_layerProgress.Remove(tile);
|
||||
}
|
||||
if (_tilesWaitingProcessing.Contains(tile))
|
||||
{
|
||||
_tilesWaitingProcessing.Remove(tile);
|
||||
}
|
||||
|
||||
if (visualizer != null)
|
||||
{
|
||||
visualizer.UnregisterTile(tile);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Public Layer Operation Api Methods for
|
||||
public virtual LayerVisualizerBase AddVectorLayerVisualizer(VectorSubLayerProperties subLayer)
|
||||
{
|
||||
//if its of type prefabitemoptions then separate the visualizer type
|
||||
LayerVisualizerBase visualizer = CreateInstance<VectorLayerVisualizer>();
|
||||
|
||||
//TODO : FIX THIS !!
|
||||
visualizer.LayerVisualizerHasChanged += UpdateTileFactory;
|
||||
|
||||
// Set honorBuildingSettings - need to set here in addition to the UI.
|
||||
// Not setting it here can lead to wrong filtering.
|
||||
|
||||
bool isPrimitiveTypeValidForBuidingIds = (subLayer.coreOptions.geometryType == VectorPrimitiveType.Polygon) || (subLayer.coreOptions.geometryType == VectorPrimitiveType.Custom);
|
||||
bool isSourceValidForBuildingIds = _properties.sourceType != VectorSourceType.MapboxStreets;
|
||||
|
||||
subLayer.honorBuildingIdSetting = isPrimitiveTypeValidForBuidingIds && isSourceValidForBuildingIds;
|
||||
// Setup visualizer.
|
||||
((VectorLayerVisualizer)visualizer).SetProperties(subLayer);
|
||||
|
||||
visualizer.Initialize();
|
||||
if (visualizer == null)
|
||||
{
|
||||
return visualizer;
|
||||
}
|
||||
|
||||
if (_layerBuilder.ContainsKey(visualizer.Key))
|
||||
{
|
||||
_layerBuilder[visualizer.Key].Add(visualizer);
|
||||
}
|
||||
else
|
||||
{
|
||||
_layerBuilder.Add(visualizer.Key, new List<LayerVisualizerBase> { visualizer });
|
||||
}
|
||||
return visualizer;
|
||||
}
|
||||
|
||||
public virtual LayerVisualizerBase AddPOIVectorLayerVisualizer(PrefabItemOptions poiSubLayer)
|
||||
{
|
||||
LayerVisualizerBase visualizer = CreateInstance<LocationPrefabsLayerVisualizer>();
|
||||
poiSubLayer.performanceOptions = _properties.performanceOptions;
|
||||
((LocationPrefabsLayerVisualizer)visualizer).SetProperties((PrefabItemOptions)poiSubLayer);
|
||||
|
||||
visualizer.LayerVisualizerHasChanged += UpdateTileFactory;
|
||||
|
||||
visualizer.Initialize();
|
||||
if (visualizer == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
if (_layerBuilder.ContainsKey(visualizer.Key))
|
||||
{
|
||||
_layerBuilder[visualizer.Key].Add(visualizer);
|
||||
}
|
||||
else
|
||||
{
|
||||
_layerBuilder.Add(visualizer.Key, new List<LayerVisualizerBase>() { visualizer });
|
||||
}
|
||||
|
||||
return visualizer;
|
||||
}
|
||||
|
||||
public virtual LayerVisualizerBase FindVectorLayerVisualizer(VectorSubLayerProperties subLayer)
|
||||
{
|
||||
if (_layerBuilder.ContainsKey(subLayer.Key))
|
||||
{
|
||||
var visualizer = _layerBuilder[subLayer.Key].Find((obj) => obj.SubLayerProperties == subLayer);
|
||||
return visualizer;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public virtual void RemoveVectorLayerVisualizer(LayerVisualizerBase subLayer)
|
||||
{
|
||||
subLayer.ClearCaches();
|
||||
if (_layerBuilder.ContainsKey(subLayer.Key))
|
||||
{
|
||||
if (Properties.vectorSubLayers.Contains(subLayer.SubLayerProperties))
|
||||
{
|
||||
Properties.vectorSubLayers.Remove(subLayer.SubLayerProperties);
|
||||
}
|
||||
else if (subLayer.SubLayerProperties is PrefabItemOptions && Properties.locationPrefabList.Contains(subLayer.SubLayerProperties as PrefabItemOptions))
|
||||
{
|
||||
Properties.locationPrefabList.Remove(subLayer.SubLayerProperties as PrefabItemOptions);
|
||||
}
|
||||
subLayer.LayerVisualizerHasChanged -= UpdateTileFactory;
|
||||
subLayer.UnbindSubLayerEvents();
|
||||
_layerBuilder[subLayer.Key].Remove(subLayer);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region AbstractFactoryOverrides
|
||||
/// <summary>
|
||||
/// Set up sublayers using VectorLayerVisualizers.
|
||||
/// </summary>
|
||||
protected override void OnInitialized()
|
||||
{
|
||||
_layerProgress = new Dictionary<UnityTile, HashSet<LayerVisualizerBase>>();
|
||||
_layerBuilder = new Dictionary<string, List<LayerVisualizerBase>>();
|
||||
|
||||
DataFetcher = ScriptableObject.CreateInstance<VectorDataFetcher>();
|
||||
DataFetcher.DataRecieved += OnVectorDataRecieved;
|
||||
DataFetcher.FetchingError += OnDataError;
|
||||
|
||||
CreatePOILayerVisualizers();
|
||||
|
||||
CreateLayerVisualizers();
|
||||
}
|
||||
|
||||
protected override void OnRegistered(UnityTile tile)
|
||||
{
|
||||
if (string.IsNullOrEmpty(MapId) || _properties.sourceOptions.isActive == false || (_properties.vectorSubLayers.Count + _properties.locationPrefabList.Count) == 0)
|
||||
{
|
||||
tile.VectorDataState = TilePropertyState.None;
|
||||
return;
|
||||
}
|
||||
tile.VectorDataState = TilePropertyState.Loading;
|
||||
_tilesWaitingResponse.Add(tile);
|
||||
VectorDataFetcherParameters parameters = new VectorDataFetcherParameters()
|
||||
{
|
||||
canonicalTileId = tile.CanonicalTileId,
|
||||
mapid = MapId,
|
||||
tile = tile,
|
||||
useOptimizedStyle = _properties.useOptimizedStyle,
|
||||
style = _properties.optimizedStyle
|
||||
};
|
||||
DataFetcher.FetchData(parameters);
|
||||
}
|
||||
|
||||
protected override void OnUnregistered(UnityTile tile)
|
||||
{
|
||||
if (_layerProgress != null && _layerProgress.ContainsKey(tile))
|
||||
{
|
||||
_layerProgress.Remove(tile);
|
||||
}
|
||||
if (_tilesWaitingResponse != null && _tilesWaitingProcessing.Contains(tile))
|
||||
{
|
||||
_tilesWaitingProcessing.Remove(tile);
|
||||
}
|
||||
|
||||
if (_layerBuilder != null)
|
||||
{
|
||||
foreach (var layer in _layerBuilder.Values)
|
||||
{
|
||||
foreach (var visualizer in layer)
|
||||
{
|
||||
visualizer.UnregisterTile(tile);
|
||||
//visualizer.LayerVisualizerHasChanged -= UpdateTileFactory;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public override void Reset()
|
||||
{
|
||||
foreach (var layerList in _layerBuilder.Values)
|
||||
{
|
||||
foreach (var layerVisualizerBase in layerList)
|
||||
{
|
||||
layerVisualizerBase.ClearCaches();
|
||||
}
|
||||
}
|
||||
_layerProgress.Clear();
|
||||
_tilesWaitingResponse.Clear();
|
||||
_tilesWaitingProcessing.Clear();
|
||||
}
|
||||
|
||||
public override void SetOptions(LayerProperties options)
|
||||
{
|
||||
_properties = (VectorLayerProperties)options;
|
||||
if (_layerBuilder != null)
|
||||
{
|
||||
RemoveAllLayerVisualiers();
|
||||
|
||||
CreatePOILayerVisualizers();
|
||||
|
||||
CreateLayerVisualizers();
|
||||
}
|
||||
}
|
||||
|
||||
public override void UpdateTileProperty(UnityTile tile, LayerUpdateArgs updateArgs)
|
||||
{
|
||||
updateArgs.property.UpdateProperty(tile);
|
||||
|
||||
if (updateArgs.property.NeedsForceUpdate())
|
||||
{
|
||||
Unregister(tile);
|
||||
}
|
||||
Register(tile);
|
||||
}
|
||||
|
||||
protected override void UpdateTileFactory(object sender, EventArgs args)
|
||||
{
|
||||
VectorLayerUpdateArgs layerUpdateArgs = args as VectorLayerUpdateArgs;
|
||||
layerUpdateArgs.factory = this;
|
||||
base.UpdateTileFactory(sender, layerUpdateArgs);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Method to be called when a tile error has occurred.
|
||||
/// </summary>
|
||||
/// <param name="e"><see cref="T:Mapbox.Map.TileErrorEventArgs"/> instance/</param>
|
||||
protected override void OnErrorOccurred(UnityTile tile, TileErrorEventArgs e)
|
||||
{
|
||||
base.OnErrorOccurred(tile, e);
|
||||
}
|
||||
|
||||
protected override void OnPostProcess(UnityTile tile)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public override void UnbindEvents()
|
||||
{
|
||||
base.UnbindEvents();
|
||||
}
|
||||
|
||||
protected override void OnUnbindEvents()
|
||||
{
|
||||
if (_layerBuilder != null)
|
||||
{
|
||||
foreach (var layer in _layerBuilder.Values)
|
||||
{
|
||||
foreach (var visualizer in layer)
|
||||
{
|
||||
visualizer.LayerVisualizerHasChanged -= UpdateTileFactory;
|
||||
visualizer.UnbindSubLayerEvents();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region DataFetcherEvents
|
||||
private void OnVectorDataRecieved(UnityTile tile, Mapbox.Map.VectorTile vectorTile)
|
||||
{
|
||||
if (tile != null)
|
||||
{
|
||||
_tilesWaitingResponse.Remove(tile);
|
||||
if (tile.VectorDataState != TilePropertyState.Unregistered)
|
||||
{
|
||||
tile.SetVectorData(vectorTile);
|
||||
|
||||
// FIXME: we can make the request BEFORE getting a response from these!
|
||||
if (tile.HeightDataState == TilePropertyState.Loading ||
|
||||
tile.RasterDataState == TilePropertyState.Loading)
|
||||
{
|
||||
tile.OnHeightDataChanged += DataChangedHandler;
|
||||
tile.OnRasterDataChanged += DataChangedHandler;
|
||||
}
|
||||
else
|
||||
{
|
||||
CreateMeshes(tile);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DataChangedHandler(UnityTile tile)
|
||||
{
|
||||
if (tile.VectorDataState != TilePropertyState.Unregistered &&
|
||||
tile.RasterDataState != TilePropertyState.Loading &&
|
||||
tile.HeightDataState != TilePropertyState.Loading)
|
||||
{
|
||||
CreateMeshes(tile);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnDataError(UnityTile tile, Mapbox.Map.VectorTile vectorTile, TileErrorEventArgs e)
|
||||
{
|
||||
if (tile != null)
|
||||
{
|
||||
_tilesWaitingResponse.Remove(tile);
|
||||
if (tile.VectorDataState != TilePropertyState.Unregistered)
|
||||
{
|
||||
tile.SetVectorData(null);
|
||||
tile.VectorDataState = TilePropertyState.Error;
|
||||
OnErrorOccurred(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Private Methods
|
||||
private void CreateMeshes(UnityTile tile)
|
||||
{
|
||||
foreach (var layerName in tile.VectorData.Data.LayerNames())
|
||||
{
|
||||
if (_layerBuilder.ContainsKey(layerName))
|
||||
{
|
||||
foreach (var builder in _layerBuilder[layerName])
|
||||
{
|
||||
CreateFeatureWithBuilder(tile, layerName, builder);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//emptylayer for visualizers that don't depend on outside data sources
|
||||
string emptyLayer = "";
|
||||
if (_layerBuilder.ContainsKey(emptyLayer))
|
||||
{
|
||||
foreach (var builder in _layerBuilder[emptyLayer])
|
||||
{
|
||||
CreateFeatureWithBuilder(tile, emptyLayer, builder);
|
||||
}
|
||||
}
|
||||
|
||||
if (!_layerProgress.ContainsKey(tile))
|
||||
{
|
||||
tile.VectorDataState = TilePropertyState.Loaded;
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateFeatureWithBuilder(UnityTile tile, string layerName, LayerVisualizerBase builder)
|
||||
{
|
||||
if (builder.Active)
|
||||
{
|
||||
if (_layerProgress.ContainsKey(tile))
|
||||
{
|
||||
_layerProgress[tile].Add(builder);
|
||||
}
|
||||
else
|
||||
{
|
||||
_layerProgress.Add(tile, new HashSet<LayerVisualizerBase> { builder });
|
||||
if (!_tilesWaitingProcessing.Contains(tile))
|
||||
{
|
||||
_tilesWaitingProcessing.Add(tile);
|
||||
}
|
||||
}
|
||||
if (layerName != "")
|
||||
{
|
||||
builder.Create(tile.VectorData.Data.GetLayer(layerName), tile, DecreaseProgressCounter);
|
||||
}
|
||||
else
|
||||
{
|
||||
//just pass the first available layer - we should create a static null layer for this
|
||||
builder.Create(tile.VectorData.Data.GetLayer(tile.VectorData.Data.LayerNames()[0]), tile, DecreaseProgressCounter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DecreaseProgressCounter(UnityTile tile, LayerVisualizerBase builder)
|
||||
{
|
||||
if (_layerProgress.ContainsKey(tile))
|
||||
{
|
||||
if (_layerProgress[tile].Contains(builder))
|
||||
{
|
||||
_layerProgress[tile].Remove(builder);
|
||||
|
||||
}
|
||||
if (_layerProgress[tile].Count == 0)
|
||||
{
|
||||
_layerProgress.Remove(tile);
|
||||
_tilesWaitingProcessing.Remove(tile);
|
||||
tile.VectorDataState = TilePropertyState.Loaded;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void CreatePOILayerVisualizers()
|
||||
{
|
||||
foreach (var item in _properties.locationPrefabList)
|
||||
{
|
||||
AddPOIVectorLayerVisualizer(item);
|
||||
}
|
||||
}
|
||||
|
||||
private void CreateLayerVisualizers()
|
||||
{
|
||||
foreach (var sublayer in _properties.vectorSubLayers)
|
||||
{
|
||||
AddVectorLayerVisualizer(sublayer);
|
||||
}
|
||||
}
|
||||
|
||||
private void RemoveAllLayerVisualiers()
|
||||
{
|
||||
//Clearing gameobjects pooled and managed by modifiers to prevent zombie gameobjects.
|
||||
foreach (var pairs in _layerBuilder)
|
||||
{
|
||||
foreach (var layerVisualizerBase in pairs.Value)
|
||||
{
|
||||
layerVisualizerBase.ClearCaches();
|
||||
}
|
||||
}
|
||||
_layerBuilder.Clear();
|
||||
}
|
||||
#endregion
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 63d97cb1cfb3f1b499c24763afa54873
|
||||
timeCreated: 1520300453
|
||||
licenseType: Pro
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user