|
|
@@ -0,0 +1,121 @@ |
|
|
using System; |
|
|
using UnityEngine; |
|
|
using UnityEngine.Rendering; |
|
|
using Random = System.Random; |
|
|
|
|
|
namespace StellarConquest.Presentation.Unity |
|
|
{ |
|
|
public class StarfieldMeshBuilder : MonoBehaviour |
|
|
{ |
|
|
public float SphereRadius = 4000; |
|
|
public int StarsCount = 0; |
|
|
public int Seed = 0; |
|
|
[Range(1, 15)] |
|
|
public float StarSizeScale = 4.5f; |
|
|
[SerializeField] AnimationCurve StarSize = new AnimationCurve(new Keyframe(0, 1), new Keyframe(1, 10)); |
|
|
[SerializeField] AnimationCurve Brightness = new AnimationCurve(new Keyframe(0, 0.8f), new Keyframe(1, 2f)); |
|
|
[SerializeField] Gradient StarColor = new Gradient(); |
|
|
|
|
|
private MeshFilter _MeshFilter; |
|
|
private Mesh _Mesh; |
|
|
private bool _IsDirty = false; |
|
|
|
|
|
#if UNITY_EDITOR |
|
|
private void OnValidate() |
|
|
{ |
|
|
_IsDirty = true; |
|
|
} |
|
|
#endif |
|
|
|
|
|
private void Update() |
|
|
{ |
|
|
if (_IsDirty) |
|
|
Build(); |
|
|
} |
|
|
|
|
|
[ContextMenu("Build")] |
|
|
public void Build() |
|
|
{ |
|
|
_IsDirty = false; |
|
|
|
|
|
if (!_MeshFilter) |
|
|
_MeshFilter = GetComponent<MeshFilter>(); |
|
|
|
|
|
if (_Mesh == null) |
|
|
{ |
|
|
_Mesh = new Mesh() { indexFormat = IndexFormat.UInt32 }; |
|
|
_Mesh.name = name; |
|
|
_MeshFilter.mesh = _Mesh; |
|
|
} |
|
|
_Mesh.Clear(); |
|
|
|
|
|
Vector3[] vertices = new Vector3[4 * StarsCount]; |
|
|
int[] triangles = new int[3 * 2 * StarsCount]; |
|
|
Vector2[] uvs = new Vector2[vertices.Length]; |
|
|
Color[] colors = new Color[vertices.Length]; |
|
|
Random rnd = new Random(Seed); |
|
|
|
|
|
for (int i = 0; i < StarsCount; i++) |
|
|
{ |
|
|
//calc position |
|
|
int index = i * 4; |
|
|
float distance = SphereRadius + SphereRadius * NextFloat() / 2f; |
|
|
float size = StarSize.Evaluate(NextFloat()) * StarSizeScale; |
|
|
|
|
|
Vector3 pos = NextOnSphere() * distance; |
|
|
Vector3 up = Vector3.Cross(pos, Math.Abs(pos.z) > distance / 2 ? Vector3.up : Vector3.right).normalized; |
|
|
Vector3 left = Vector3.Cross(-up, pos).normalized; |
|
|
|
|
|
//vertices |
|
|
vertices[index + 0] = pos + (left + up) * size; |
|
|
vertices[index + 1] = pos + (-left + up) * size; |
|
|
vertices[index + 2] = pos + (-left - up) * size; |
|
|
vertices[index + 3] = pos + (left - up) * size; |
|
|
|
|
|
//uv |
|
|
uvs[index + 0] = new Vector2(0, 0); |
|
|
uvs[index + 1] = new Vector2(1, 0); |
|
|
uvs[index + 2] = new Vector2(1, 1); |
|
|
uvs[index + 3] = new Vector2(0, 1); |
|
|
|
|
|
//triangles |
|
|
var iTr = i * 2 * 3; |
|
|
triangles[iTr++] = index + 0; |
|
|
triangles[iTr++] = index + 1; |
|
|
triangles[iTr++] = index + 2; |
|
|
|
|
|
triangles[iTr++] = index + 0; |
|
|
triangles[iTr++] = index + 2; |
|
|
triangles[iTr++] = index + 3; |
|
|
|
|
|
//color |
|
|
Color color = Brightness.Evaluate(NextFloat()) * StarColor.Evaluate(NextFloat()); |
|
|
colors[index + 0] = colors[index + 1] = colors[index + 2] = colors[index + 3] = color; |
|
|
} |
|
|
|
|
|
_Mesh.SetVertices(vertices); |
|
|
_Mesh.SetUVs(0, uvs); |
|
|
_Mesh.SetTriangles(triangles, 0); |
|
|
_Mesh.SetColors(colors); |
|
|
|
|
|
_Mesh.RecalculateNormals(); |
|
|
_Mesh.RecalculateBounds(); |
|
|
|
|
|
float NextFloat() |
|
|
{ |
|
|
return (float)rnd.NextDouble(); |
|
|
} |
|
|
|
|
|
Vector3 NextOnSphere() |
|
|
{ |
|
|
var theta = 2 * Math.PI * rnd.NextDouble(); |
|
|
var phi = Math.Acos(2 * rnd.NextDouble() - 1.0); |
|
|
var sinPhi = Math.Sin(phi); |
|
|
var x = Math.Cos(theta) * sinPhi; |
|
|
var y = Math.Sin(theta) * sinPhi; |
|
|
var z = Math.Cos(phi); |
|
|
return new Vector3((float)x, (float)y, (float)z); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |