-
-
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).
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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