Last active
February 13, 2018 09:34
-
-
Save mihakrajnc/bfcae06a16a0991cb5a41601663b8c9e to your computer and use it in GitHub Desktop.
A snap to terrain modifier for Mapbox Unity that uses Raycasting.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using Mapbox.Unity.Map; | |
using Mapbox.Unity.MeshGeneration.Data; | |
using Mapbox.Unity.MeshGeneration.Modifiers; | |
using UnityEngine; | |
[CreateAssetMenu(menuName = "Mapbox/Modifiers/Custom/Snap Terrain Raycast Modifier")] | |
public class SnapTerrainRaycastModifier : MeshModifier | |
{ | |
private const int RAY_LENGTH = 50; | |
[SerializeField] private LayerMask terrainMask; | |
public override ModifierType Type | |
{ | |
get { return ModifierType.Preprocess; } | |
} | |
public override void Run(VectorFeatureUnity feature, MeshData md, UnityTile tile = null) | |
{ | |
float worldScale = FindObjectOfType<AbstractMap>().WorldRelativeScale; | |
if (md.Vertices.Count > 0) | |
{ | |
for (int i = 0; i < md.Vertices.Count; i++) | |
{ | |
var h = tile.QueryHeightData((float) ((md.Vertices[i].x + tile.Rect.Size.x / 2) / tile.Rect.Size.x), | |
(float) ((md.Vertices[i].z + tile.Rect.Size.y / 2) / tile.Rect.Size.y)); | |
RaycastHit hit; | |
Vector3 rayCenter = | |
new Vector3(md.Vertices[i].x * worldScale + tile.transform.position.x, | |
h * worldScale + RAY_LENGTH / 2, | |
md.Vertices[i].z * worldScale + tile.transform.position.z); | |
if (Physics.Raycast(rayCenter, Vector3.down, out hit, RAY_LENGTH, terrainMask)) | |
{ | |
md.Vertices[i] += new Vector3(0, hit.point.y / worldScale, 0); | |
} | |
else | |
{ | |
// Raycasting sometimes fails at terrain boundaries, fallback to tile height data. | |
md.Vertices[i] += new Vector3(0, h, 0); | |
} | |
} | |
} | |
else | |
{ | |
foreach (var sub in feature.Points) | |
{ | |
for (int i = 0; i < sub.Count; i++) | |
{ | |
var h = tile.QueryHeightData((float) ((sub[i].x + tile.Rect.Size.x / 2) / tile.Rect.Size.x), | |
(float) ((sub[i].z + tile.Rect.Size.y / 2) / tile.Rect.Size.y)); | |
RaycastHit hit; | |
Vector3 rayCenter = | |
new Vector3(sub[i].x * worldScale + tile.transform.position.x, | |
h * worldScale + RAY_LENGTH / 2, | |
sub[i].z * worldScale + tile.transform.position.z); | |
if (Physics.Raycast(rayCenter, Vector3.down, out hit, RAY_LENGTH, terrainMask)) | |
{ | |
sub[i] += new Vector3(0, hit.point.y / worldScale, 0); | |
} | |
else | |
{ | |
// Raycasting sometimes fails at terrain boundaries, fallback to tile height data. | |
sub[i] += new Vector3(0, h, 0); | |
} | |
} | |
} | |
} | |
} | |
} |
When making use of snap terrain modifiers such as this, the UnityTile paramter tile is always Null - where is the tile retreived from?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
NOTE: You need to configure your terrain to be added to a layer, and use the layer name with this modifier (default "Terrain").