137 lines
3.6 KiB
C#
137 lines
3.6 KiB
C#
|
using System.Collections;
|
|||
|
using System.Collections.Generic;
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
[ExecuteInEditMode]
|
|||
|
[RequireComponent(typeof(MeshRenderer))]
|
|||
|
[RequireComponent(typeof(MeshFilter))]
|
|||
|
class TerrainScript : MonoBehaviour {
|
|||
|
|
|||
|
int m_SegmentCount_x;
|
|||
|
int m_SegmentCount_z;
|
|||
|
float m_Size = 0.001f;
|
|||
|
MeshFilter filter;
|
|||
|
Transform controllerTarget;
|
|||
|
Texture2D m_HeightMap;
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
|
|||
|
void Start() {
|
|||
|
|
|||
|
filter = GetComponent<MeshFilter>();
|
|||
|
controllerTarget = GameObject.Find("ControllerTarget").transform;
|
|||
|
m_HeightMap = Resources.Load("mars_height") as Texture2D;
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public float GetY(float x, float z, float heightScale)
|
|||
|
{
|
|||
|
Color mapColour = m_HeightMap.GetPixelBilinear(x, z);
|
|||
|
return sinh((mapColour.grayscale-0.5f)*heightScale);
|
|||
|
}
|
|||
|
|
|||
|
private float sinh(float x) {
|
|||
|
return ((1 - Mathf.Exp(-2*x))/(2*(Mathf.Exp(-x))));
|
|||
|
}
|
|||
|
|
|||
|
void Update() {
|
|||
|
|
|||
|
m_SegmentCount_x = Mathf.FloorToInt(controllerTarget.position.x / m_Size);
|
|||
|
m_SegmentCount_z = Mathf.FloorToInt(controllerTarget.position.z / m_Size);
|
|||
|
|
|||
|
|
|||
|
MeshBuilder meshBuilder = new MeshBuilder();
|
|||
|
|
|||
|
float heightScale = ((controllerTarget.rotation.eulerAngles.y)/360.0f)*0.1f;
|
|||
|
|
|||
|
for (int i = 0; i <= m_SegmentCount_z; i++)
|
|||
|
{
|
|||
|
float z = m_Size * i;
|
|||
|
float v = (1.0f / m_SegmentCount_z) * i;
|
|||
|
|
|||
|
for (int j = 0; j <= m_SegmentCount_x; j++)
|
|||
|
{
|
|||
|
float x = m_Size * j;
|
|||
|
float u = (1.0f / m_SegmentCount_x) * j;
|
|||
|
|
|||
|
Vector3 offset = new Vector3(x, GetY(x,z, heightScale), z);
|
|||
|
|
|||
|
Vector2 uv = new Vector2(u, v);
|
|||
|
bool buildTriangles = i > 0 && j > 0;
|
|||
|
|
|||
|
BuildQuadForGrid(meshBuilder, offset, uv, buildTriangles, m_SegmentCount_x + 1);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
filter.sharedMesh = meshBuilder.CreateMesh();
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
void BuildQuadForGrid(MeshBuilder meshBuilder, Vector3 position, Vector2 uv,
|
|||
|
bool buildTriangles, int vertsPerRow)
|
|||
|
{
|
|||
|
meshBuilder.Vertices.Add(position);
|
|||
|
meshBuilder.UVs.Add(uv);
|
|||
|
|
|||
|
if (buildTriangles)
|
|||
|
{
|
|||
|
int baseIndex = meshBuilder.Vertices.Count - 1;
|
|||
|
|
|||
|
int index0 = baseIndex;
|
|||
|
int index1 = baseIndex - 1;
|
|||
|
int index2 = baseIndex - vertsPerRow;
|
|||
|
int index3 = baseIndex - vertsPerRow - 1;
|
|||
|
|
|||
|
meshBuilder.AddTriangle(index0, index2, index1);
|
|||
|
meshBuilder.AddTriangle(index2, index3, index1);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
|
|||
|
public class MeshBuilder
|
|||
|
{
|
|||
|
private List<Vector3> m_Vertices = new List<Vector3>();
|
|||
|
public List<Vector3> Vertices { get { return m_Vertices; } }
|
|||
|
|
|||
|
private List<Vector3> m_Normals = new List<Vector3>();
|
|||
|
public List<Vector3> Normals { get { return m_Normals; } }
|
|||
|
|
|||
|
private List<Vector2> m_UVs = new List<Vector2>();
|
|||
|
public List<Vector2> UVs { get { return m_UVs; } }
|
|||
|
|
|||
|
private List<int> m_Indices = new List<int>();
|
|||
|
|
|||
|
public void AddTriangle(int index0, int index1, int index2)
|
|||
|
{
|
|||
|
m_Indices.Add(index0);
|
|||
|
m_Indices.Add(index1);
|
|||
|
m_Indices.Add(index2);
|
|||
|
}
|
|||
|
|
|||
|
public Mesh CreateMesh()
|
|||
|
{
|
|||
|
Mesh mesh = new Mesh();
|
|||
|
|
|||
|
mesh.vertices = m_Vertices.ToArray();
|
|||
|
mesh.triangles = m_Indices.ToArray();
|
|||
|
|
|||
|
//Normals are optional. Only use them if we have the correct amount:
|
|||
|
if (m_Normals.Count == m_Vertices.Count)
|
|||
|
mesh.normals = m_Normals.ToArray();
|
|||
|
|
|||
|
|
|||
|
mesh.uv = m_UVs.ToArray();
|
|||
|
|
|||
|
mesh.RecalculateBounds();
|
|||
|
|
|||
|
return mesh;
|
|||
|
}
|
|||
|
}
|