176 lines
4.7 KiB
C#
176 lines
4.7 KiB
C#
using System.Collections.Generic;
|
|
using System.IO;
|
|
using UnityEngine;
|
|
|
|
public class MeshBaker : MonoBehaviour
|
|
{
|
|
private struct PointWithUV
|
|
{
|
|
public Vector3 pos;
|
|
|
|
public Vector2 uv;
|
|
|
|
public Color color;
|
|
|
|
public float dist;
|
|
}
|
|
|
|
public Mesh mesh;
|
|
|
|
[Range(0f, 98f)]
|
|
public int sliceIndex;
|
|
|
|
[Range(64f, 256f)]
|
|
public int resolution = 64;
|
|
|
|
[Range(0f, 0.1f)]
|
|
public float sliceThreshold = 0.0044f;
|
|
|
|
[HideInInspector]
|
|
public List<float> slicesY;
|
|
|
|
[HideInInspector]
|
|
public Bounds bounds;
|
|
|
|
private Texture2D result;
|
|
|
|
public void Bake()
|
|
{
|
|
Vector3[] vertices = mesh.vertices;
|
|
for (int i = 0; i < vertices.Length; i++)
|
|
{
|
|
vertices[i].y = Mathf.Max(vertices[i].y, 0f);
|
|
}
|
|
slicesY = new List<float>();
|
|
bounds = new Bounds
|
|
{
|
|
min = vertices[0],
|
|
max = vertices[0]
|
|
};
|
|
for (int j = 0; j < vertices.Length; j++)
|
|
{
|
|
bounds.Encapsulate(vertices[j]);
|
|
bool flag = false;
|
|
for (int k = 0; k < slicesY.Count; k++)
|
|
{
|
|
if (Mathf.Abs(slicesY[k] - vertices[j].z) < sliceThreshold)
|
|
{
|
|
flag = true;
|
|
break;
|
|
}
|
|
}
|
|
if (!flag)
|
|
{
|
|
slicesY.Add(vertices[j].z);
|
|
}
|
|
}
|
|
result = new Texture2D(resolution, slicesY.Count);
|
|
for (int l = 0; l < slicesY.Count; l++)
|
|
{
|
|
float sliceLength;
|
|
List<PointWithUV> slice = GetSlice(l, out sliceLength);
|
|
for (int m = 0; m < resolution; m++)
|
|
{
|
|
int n = 0;
|
|
float num;
|
|
for (num = (float)m / (float)(resolution - 1); n < slice.Count - 1 && !(slice[n].dist / sliceLength > num); n++)
|
|
{
|
|
}
|
|
float a = slice[n - 1].dist / sliceLength;
|
|
float b = slice[n].dist / sliceLength;
|
|
float t = Mathf.InverseLerp(a, b, num);
|
|
Vector3 vector = Vector3.Lerp(slice[n - 1].pos, slice[n].pos, t);
|
|
Vector3 vector2 = new Vector3((1f - num) * bounds.size.x + bounds.min.x, bounds.min.y, 0f);
|
|
Vector3 vector3 = vector - vector2;
|
|
float z = Mathf.Lerp(slice[n - 1].color.r, slice[n].color.r, t);
|
|
vector3 = new Vector3(vector3.x / (2f * bounds.size.x) + 0.5f, vector3.y / bounds.size.y, z);
|
|
result.SetPixel(m, l, new Color(vector3.x, vector3.y, vector3.z));
|
|
}
|
|
}
|
|
result.Apply();
|
|
byte[] bytes = result.EncodeToPNG();
|
|
string text = Application.dataPath + "/Artifacts/" + mesh.name + ".png";
|
|
File.WriteAllBytes(text, bytes);
|
|
Debug.Log("Texture file written at " + text);
|
|
}
|
|
|
|
private List<PointWithUV> GetSlice(int idx, out float sliceLength)
|
|
{
|
|
Vector3[] vertices = mesh.vertices;
|
|
Color[] colors = mesh.colors;
|
|
Vector2[] uv = mesh.uv;
|
|
List<PointWithUV> list = new List<PointWithUV>();
|
|
for (int i = 0; i < vertices.Length; i++)
|
|
{
|
|
vertices[i].y = Mathf.Max(vertices[i].y, 0f);
|
|
if (!(Mathf.Abs(slicesY[idx] - vertices[i].z) >= sliceThreshold))
|
|
{
|
|
Vector3 pos = vertices[i];
|
|
pos.z = 0f;
|
|
PointWithUV item = new PointWithUV
|
|
{
|
|
pos = pos
|
|
};
|
|
if (i < uv.Length)
|
|
{
|
|
item.uv = uv[i];
|
|
}
|
|
if (i < colors.Length)
|
|
{
|
|
item.color = colors[i];
|
|
}
|
|
list.Add(item);
|
|
}
|
|
}
|
|
list.Sort((PointWithUV pointWithUV, PointWithUV b) => (pointWithUV.uv.x > b.uv.x) ? 1 : (-1));
|
|
sliceLength = 0f;
|
|
Vector3 a = list[0].pos;
|
|
for (int num = 1; num < list.Count; num++)
|
|
{
|
|
Vector3 pos2 = list[num].pos;
|
|
sliceLength += Vector3.Distance(a, pos2);
|
|
a = pos2;
|
|
list[num] = new PointWithUV
|
|
{
|
|
pos = list[num].pos,
|
|
uv = list[num].uv,
|
|
color = list[num].color,
|
|
dist = sliceLength
|
|
};
|
|
}
|
|
return list;
|
|
}
|
|
|
|
private void OnDrawGizmos()
|
|
{
|
|
if (slicesY == null)
|
|
{
|
|
return;
|
|
}
|
|
sliceIndex = Mathf.Min(sliceIndex, slicesY.Count - 1);
|
|
Gizmos.color = Color.green;
|
|
Gizmos.DrawRay(base.transform.position + new Vector3(bounds.min.x, bounds.min.y, 0f), new Vector3(bounds.size.x, 0f, 0f));
|
|
Gizmos.DrawRay(base.transform.position + new Vector3(bounds.min.x, bounds.min.y, 0f), new Vector3(0f, bounds.size.y, 0f));
|
|
Gizmos.DrawRay(base.transform.position + new Vector3(bounds.max.x, bounds.max.y, 0f), -new Vector3(bounds.size.x, 0f, 0f));
|
|
Gizmos.DrawRay(base.transform.position + new Vector3(bounds.max.x, bounds.max.y, 0f), -new Vector3(0f, bounds.size.y, 0f));
|
|
float sliceLength;
|
|
List<PointWithUV> slice = GetSlice(sliceIndex, out sliceLength);
|
|
Vector3 vector = slice[0].pos;
|
|
for (int i = 1; i < slice.Count; i++)
|
|
{
|
|
Vector3 pos = slice[i].pos;
|
|
float num = slice[i].dist / sliceLength;
|
|
Gizmos.color = new Color(num, 0f, 0f);
|
|
if (num >= 0.8f && num <= 0.85f)
|
|
{
|
|
Gizmos.color = new Color(0f, 1f, 0f);
|
|
}
|
|
Gizmos.DrawLine(base.transform.position + vector, base.transform.position + pos);
|
|
Vector3 vector2 = new Vector3((1f - slice[i].dist / sliceLength) * bounds.size.x + bounds.min.x, bounds.min.y, 0f);
|
|
Gizmos.color = Color.blue;
|
|
Gizmos.DrawLine(base.transform.position + vector2, base.transform.position + pos);
|
|
vector = pos;
|
|
}
|
|
}
|
|
}
|