This repository has been archived on 2025-08-02. You can view files and clone it, but cannot push or open issues or pull requests.
Files
Cryville.EEW.Unity/Assets/Cryville.EEW.Unity/Map/PolygonRenderer.cs

110 lines
3.1 KiB
C#

using Cryville.EEW.Core.Map;
using Poly2Tri;
using System.Buffers;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using UnityEngine;
using Color = UnityEngine.Color;
namespace Cryville.EEW.Unity.Map {
[RequireComponent(typeof(MeshFilter))]
[RequireComponent(typeof(MeshRenderer))]
class PolygonRenderer : MonoBehaviour {
Material _sharedMaterial;
public Material Material {
get => _meshRenderer.sharedMaterial;
set {
if (value == _sharedMaterial) return;
if (_sharedMaterial != null) Destroy(_meshRenderer.sharedMaterial);
_sharedMaterial = value;
if (_sharedMaterial == null) return;
_meshRenderer.sharedMaterial = Instantiate(_sharedMaterial);
_meshRenderer.sharedMaterial.color = m_color;
}
}
[SerializeField]
Color m_color = Color.white;
public Color Color {
get => m_color;
set {
if (m_color == value) return;
m_color = value;
_meshRenderer.material.color = value;
}
}
Mesh _mesh;
MeshFilter _meshFilter;
MeshRenderer _meshRenderer;
void Awake() {
_meshFilter = GetComponent<MeshFilter>();
_meshRenderer = GetComponent<MeshRenderer>();
if (!_meshFilter.mesh) {
_meshFilter.mesh = new();
}
_mesh = _meshFilter.mesh;
if (_sharedMaterial == null && _meshRenderer.sharedMaterial != null) {
_sharedMaterial = _meshRenderer.sharedMaterial;
_meshRenderer.sharedMaterial = Instantiate(_sharedMaterial);
_meshRenderer.sharedMaterial.color = m_color;
}
}
void OnDestroy() {
Destroy(_mesh);
Destroy(Material);
}
public void SetPolygon(IEnumerable<IEnumerable<PointF>> polygon) {
_mesh.Clear();
Polygon convertedPolygon = null;
foreach (var loop in polygon) {
var convertedLoop = new Polygon(loop.Select(p => {
var v = MapTileUtils.WorldToTilePos(p).ToVector2();
return new PolygonPoint(v.x, v.y);
}));
if (convertedPolygon is null) {
convertedPolygon = convertedLoop;
}
else {
convertedPolygon.AddHole(convertedLoop);
}
}
var tcx = new DTSweepContext();
tcx.PrepareTriangulation(convertedPolygon);
DTSweep.Triangulate(tcx);
var codeToIndex = new Dictionary<uint, int>();
int vertexCount = convertedPolygon.Points.Count;
if (convertedPolygon.Holes != null) {
foreach (var hole in convertedPolygon.Holes) {
vertexCount += hole.Points.Count;
}
}
var vertices = ArrayPool<Vector3>.Shared.Rent(vertexCount);
var triangles = ArrayPool<int>.Shared.Rent(convertedPolygon.Triangles.Count * 3);
int vi = 0, ii = 0;
foreach (var tri in convertedPolygon.Triangles) {
for (int i = 2; i >= 0; --i) {
var p = tri.Points[i];
if (!codeToIndex.TryGetValue(p.VertexCode, out int index)) {
codeToIndex.Add(p.VertexCode, index = vi++);
vertices[index] = new(p.Xf, p.Yf);
}
triangles[ii++] = index;
}
}
_mesh.SetVertices(vertices, 0, vi);
_mesh.SetTriangles(triangles, 0, ii, 0);
_mesh.RecalculateNormals();
_mesh.RecalculateBounds();
ArrayPool<int>.Shared.Return(triangles);
ArrayPool<Vector3>.Shared.Return(vertices);
}
}
}