using System.Collections.Generic; using UnityEngine; namespace Vanguard.Board3D { /// Плоские рамки кругов и зон в плоскости XZ. internal static class BoardMeshLibrary { private static readonly Dictionary Cache = new Dictionary(); 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), }, // Задняя грань смотрит вниз: без зеркального U рубашка // читается отражённой, когда карта перевёрнута лицом вниз. uv = front ? new[] { new Vector2(0f, 0f), new Vector2(1f, 0f), new Vector2(1f, 1f), new Vector2(0f, 1f), } : new[] { new Vector2(1f, 0f), new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(1f, 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(16); var triangles = new List(48); var uvs = new List(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 vertices, ICollection triangles, ICollection 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); } } }