-
Notifications
You must be signed in to change notification settings - Fork 7
/
MeshToMap.cs
135 lines (105 loc) · 3.7 KB
/
MeshToMap.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class MapSet
{
public int vtxCount;
public Texture2D position;
public Texture2D uv;
public Texture2D normal;
}
public class MeshToMap
{
public static MapSet ComputeMap(Mesh mesh, float pointCountPerArea)
{
IEnumerable<Vector3> vertices = mesh.vertices;
IEnumerable<Vector2> uvList = mesh.uv;
IEnumerable<Vector3> normals = mesh.normals;
if (pointCountPerArea > 0f)
{
(vertices, uvList, normals) = DividePolygon(mesh, pointCountPerArea);
}
var count = vertices.Count();
var (width, height) = CalcTexSize(count);
var positions = vertices.Select(vtx => new Color(vtx.x, vtx.y, vtx.z));
var uvs = uvList.Select(uv => new Color(uv.x, uv.y, 0f));
var nrms = normals.Select(nrm => new Color(nrm.x, nrm.y, nrm.z));
var mapSet = new MapSet()
{
vtxCount = count,
position = CreateMap(positions, width, height),
uv = CreateMap(uvs, width, height),
normal = CreateMap(nrms, width, height)
};
return mapSet;
}
// Increase points to be evenly spaced
static (List<Vector3>, List<Vector2>, List<Vector3>) DividePolygon(Mesh mesh, float pointCountPerArea = 1f)
{
var triangles = mesh.triangles;
var vertices = mesh.vertices;
var uvs = mesh.uv;
var normals = mesh.normals;
var posList = new List<Vector3>();
var uvList = new List<Vector2>();
var nrmList = new List<Vector3>();
for (var i = 0; i < triangles.Length; i += 3)
{
var idx0 = triangles[i];
var idx1 = triangles[i + 1];
var idx2 = triangles[i + 2];
var pos0 = vertices[idx0];
var pos1 = vertices[idx1];
var pos2 = vertices[idx2];
var uv0 = uvs[idx0];
var uv1 = uvs[idx1];
var uv2 = uvs[idx2];
var nrm0 = normals[idx0];
var nrm1 = normals[idx1];
var nrm2 = normals[idx2];
var area = Vector3.Cross(pos1 - pos0, pos2 - pos0).magnitude * 0.5f; // 三角形pos0,pos1,pos2の面積
var pointNum = Mathf.CeilToInt(area * pointCountPerArea);
for (var pIdx = 0; pIdx < pointNum; ++pIdx)
{
var wait0 = Random.value;
var wait1 = Random.value;
if ( wait0 + wait1 > 1f)
{
wait0 = 1f - wait0;
wait1 = 1f - wait1;
}
var wait2 = 1f - wait0 - wait1;
var pos = pos0 * wait0 + pos1 * wait1 + pos2 * wait2;
var uv = uv0 * wait0 + uv1 * wait1 + uv2 * wait2;
var nrm = nrm0 * wait0 + nrm1 * wait1 + nrm2 * wait2;
posList.Add(pos);
uvList.Add(uv);
nrmList.Add(nrm);
}
}
return (posList, uvList, nrmList);
}
static Texture2D CreateMap(IEnumerable<Color> colors, int width, int height)
{
var tex = new Texture2D(width, height, TextureFormat.RGBAFloat, false);
tex.filterMode = FilterMode.Point;
tex.wrapMode = TextureWrapMode.Clamp;
var buf = new Color[width * height];
var idx = 0;
foreach (var color in colors)
{
buf[idx] = color;
idx++;
}
tex.SetPixels(buf);
tex.Apply();
return tex;
}
static (int, int) CalcTexSize(int count)
{
float r = Mathf.Sqrt(count);
var width = (int)Mathf.Ceil(r);
var height = width;
return (width, height);
}
}