Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save unitycoder/501b57ab7c84b8d9c8868c07d2b80d40 to your computer and use it in GitHub Desktop.
Save unitycoder/501b57ab7c84b8d9c8868c07d2b80d40 to your computer and use it in GitHub Desktop.
A Unity editor script which takes a mesh and generates a texture based on the UVs where each triangle is assigned a random greyscale color (place the script inside a folder named Editor).
#if UNITY_EDITOR
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;
using UnityEditor;
using UnityEditor.UIElements;
// Based on: https://forum.unity.com/threads/save-rendertexture-or-texture2d-as-image-file-utility.1325130/
public class TriangleTexturePluginWindow : EditorWindow
{
private ObjectField mesh;
private TextField filepath;
private Vector2IntField size;
private Button button;
[MenuItem("Tools/Convert Mesh to Random Triangle Color Texture")]
public static void ShowWindow()
{
var window = GetWindow<TriangleTexturePluginWindow>();
window.minSize = new Vector2(300, 100);
window.titleContent = new GUIContent("Mesh -> Triangle Texture");
}
public void CreateGUI()
{
VisualElement root = rootVisualElement;
mesh = new ObjectField("Mesh") { objectType = typeof(Mesh) };
root.Add(mesh);
filepath = new TextField("Filepath") { value = "Assets/texture.png" };
root.Add(filepath);
size = new Vector2IntField("Size") { value = new Vector2Int(1024, 1024) };
root.Add(size);
button = new Button(Save) { text = "Save" };
root.Add(button);
}
private void Save()
{
if (size.value.x <= 0 || size.value.y <= 0)
{
Debug.LogError("Size must be positive.");
}
TriangleTexturePlugin.GenerateColors(filepath.value, size.value.x, size.value.y, mesh.value as Mesh);
}
}
// Based on: https://forum.unity.com/threads/save-rendertexture-or-texture2d-as-image-file-utility.1325130/
public class TriangleTexturePlugin
{
public static void GenerateColors(string filepath, int width, int height, Mesh mesh)
{
var pixelCount = width * height;
var pixels = new Color[pixelCount];
int[] triangles = mesh.triangles;
Vector2[] uvs = mesh.uv;
for (int i = 0; i < mesh.triangles.Length; i += 3)
{
int vert1 = mesh.triangles[i];
int vert2 = mesh.triangles[i + 1];
int vert3 = mesh.triangles[i + 2];
Vector2 uv1 = Mod(uvs[triangles[i]]);
Vector2 uv2 = Mod(uvs[triangles[i + 1]]);
Vector2 uv3 = Mod(uvs[triangles[i + 2]]);
float rand = Random.value;
int minX = (int)(Mathf.Min(uv1.x, Mathf.Min(uv2.x, uv3.x)) * width);
int maxX = (int)(Mathf.Min((Mathf.Max(uv1.x, Mathf.Max(uv2.x, uv3.x)) * width), width));
int minY = (int)(Mathf.Min(uv1.y, Mathf.Min(uv2.y, uv3.y)) * height);
int maxY = (int)(Mathf.Min((Mathf.Max(uv1.y, Mathf.Max(uv2.y, uv3.y)) * height), height));
for (int x = minX; x <= maxX; ++x)
{
for (int y = minY; y <= maxY; ++y)
{
Vector2 point = new Vector2(x, y);
if (PointIsInTriangle(uv1 * width, uv2 * width, uv3 * width, point))
{
pixels[x + y * width] = new Color(rand, rand, rand, 1.0f);
}
}
}
}
var tex = new Texture2D(width, height);
tex.SetPixels(pixels);
tex.Apply(true, false);
SaveTextureToFile(tex, filepath);
}
private static Vector2 Mod(Vector2 inVector)
{
return new Vector2(inVector.x % 1.0f, inVector.y % 1.0f);
}
// Based on: https://stackoverflow.com/questions/2049582/how-to-determine-if-a-point-is-in-a-2d-triangle
private static float Sign(Vector2 v1, Vector2 v2, Vector2 v3)
{
return (v1.x - v3.x) * (v2.y - v3.y) - (v2.x - v3.x) * (v1.y - v3.y);
}
private static bool PointIsInTriangle(Vector2 v1, Vector2 v2, Vector2 v3, Vector2 point)
{
float d1, d2, d3;
bool hasNeg, hasPos;
d1 = Sign(point, v1, v2);
d2 = Sign(point, v2, v3);
d3 = Sign(point, v3, v1);
hasNeg = (d1 < 0) || (d2 < 0) || (d3 < 0);
hasPos = (d1 > 0) || (d2 > 0) || (d3 > 0);
return !(hasNeg && hasPos);
}
private static void SaveTextureToFile(Texture2D tex, string filepath)
{
string uniqueFilepath = AssetDatabase.GenerateUniqueAssetPath(filepath);
System.IO.File.WriteAllBytes(uniqueFilepath, tex.EncodeToPNG());
AssetDatabase.Refresh();
Object file = AssetDatabase.LoadAssetAtPath(uniqueFilepath, typeof(Texture2D));
Debug.Log($"Texture saved to [{uniqueFilepath}]", file);
}
}
#endif
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment