VanguardReMaster/client/Assets/Vanguard/Runtime/Board3D/View/BoardMeshLibrary.cs

157 lines
5.4 KiB
C#

using System.Collections.Generic;
using UnityEngine;
namespace Vanguard.Board3D
{
/// <summary>Плоские рамки кругов и зон в плоскости XZ.</summary>
internal static class BoardMeshLibrary
{
private static readonly Dictionary<string, Mesh> Cache =
new Dictionary<string, Mesh>();
public static Mesh Frame(float width, float depth, float border)
{
var key = Mathf.RoundToInt(width * 1000f)
+ ":" + Mathf.RoundToInt(depth * 1000f)
+ ":" + Mathf.RoundToInt(border * 1000f);
if (Cache.TryGetValue(key, out var cached) && cached != null)
return cached;
var mesh = BuildFrame(width, depth, border);
mesh.hideFlags = HideFlags.DontSave;
Cache[key] = mesh;
return mesh;
}
public static Mesh CardFace(float width, float height, bool front)
{
var key = (front ? "front:" : "back:")
+ Mathf.RoundToInt(width * 1000f)
+ ":" + Mathf.RoundToInt(height * 1000f);
if (Cache.TryGetValue(key, out var cached) && cached != null)
return cached;
var halfW = width * 0.5f;
var halfH = height * 0.5f;
var normal = front ? Vector3.up : Vector3.down;
var mesh = new Mesh
{
name = front ? "Card Front" : "Card Back",
hideFlags = HideFlags.DontSave,
vertices = new[]
{
new Vector3(-halfW, 0f, -halfH),
new Vector3(halfW, 0f, -halfH),
new Vector3(halfW, 0f, halfH),
new Vector3(-halfW, 0f, halfH),
},
uv = new[]
{
new Vector2(0f, 0f),
new Vector2(1f, 0f),
new Vector2(1f, 1f),
new Vector2(0f, 1f),
},
normals = new[] { normal, normal, normal, normal },
triangles = new[]
{
0, 1, 2, 0, 2, 3,
0, 2, 1, 0, 3, 2,
},
};
mesh.RecalculateBounds();
Cache[key] = mesh;
return mesh;
}
private static Mesh BuildFrame(float width, float depth, float border)
{
var halfW = width * 0.5f;
var halfD = depth * 0.5f;
border = Mathf.Clamp(border, 0.005f, Mathf.Min(halfW, halfD) * 0.9f);
var vertices = new List<Vector3>(16);
var triangles = new List<int>(48);
var uvs = new List<Vector2>(16);
AddQuad(
vertices, triangles, uvs,
new Vector3(-halfW, 0f, halfD - border),
new Vector3(halfW, 0f, halfD - border),
new Vector3(halfW, 0f, halfD),
new Vector3(-halfW, 0f, halfD));
AddQuad(
vertices, triangles, uvs,
new Vector3(-halfW, 0f, -halfD),
new Vector3(halfW, 0f, -halfD),
new Vector3(halfW, 0f, -halfD + border),
new Vector3(-halfW, 0f, -halfD + border));
AddQuad(
vertices, triangles, uvs,
new Vector3(-halfW, 0f, -halfD + border),
new Vector3(-halfW + border, 0f, -halfD + border),
new Vector3(-halfW + border, 0f, halfD - border),
new Vector3(-halfW, 0f, halfD - border));
AddQuad(
vertices, triangles, uvs,
new Vector3(halfW - border, 0f, -halfD + border),
new Vector3(halfW, 0f, -halfD + border),
new Vector3(halfW, 0f, halfD - border),
new Vector3(halfW - border, 0f, halfD - border));
var mesh = new Mesh
{
name = "Board Frame",
vertices = vertices.ToArray(),
triangles = triangles.ToArray(),
uv = uvs.ToArray(),
};
var normals = new Vector3[vertices.Count];
for (var i = 0; i < normals.Length; i++)
normals[i] = Vector3.up;
mesh.normals = normals;
mesh.RecalculateBounds();
return mesh;
}
private static void AddQuad(
ICollection<Vector3> vertices,
ICollection<int> triangles,
ICollection<Vector2> uvs,
Vector3 a,
Vector3 b,
Vector3 c,
Vector3 d)
{
var start = vertices.Count;
vertices.Add(a);
vertices.Add(b);
vertices.Add(c);
vertices.Add(d);
uvs.Add(new Vector2(0f, 0f));
uvs.Add(new Vector2(1f, 0f));
uvs.Add(new Vector2(1f, 1f));
uvs.Add(new Vector2(0f, 1f));
// Две стороны: рамки видны и сверху, и при наклоне камеры.
triangles.Add(start);
triangles.Add(start + 1);
triangles.Add(start + 2);
triangles.Add(start);
triangles.Add(start + 2);
triangles.Add(start + 3);
triangles.Add(start);
triangles.Add(start + 2);
triangles.Add(start + 1);
triangles.Add(start);
triangles.Add(start + 3);
triangles.Add(start + 2);
}
}
}