Color extraction from Vertex/UV
Color extraction from Vertex/UV
This tool extract color from a mesh using its uv and get its world position to emit particles
C#, Unity
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;
[System.Serializable]
public struct ColorAdjustParticle
{
[Tooltip("Object that contains particle system component")]
public GameObject Obj;
[Tooltip("Color value level")]
public bool SingleColor;
}
[System.Serializable]
public struct ColorAdjustMesh
{
[Tooltip("Object that contains particle system component")]
public GameObject Obj;
}
[ExecuteInEditMode]
public class ParticleTextureColor : MonoBehaviour {
[Tooltip("Reference Card Texture")]
public Texture2D TextureImg;
[Tooltip("Mipmap Level of the Card Texture")]
public bool UseMipmap = false;
[Tooltip("Mipmap Level of the Card Texture")]
public int MipmapLevel = 0;
[Space(10)]
[Tooltip("Particle systems that will be affected by this color module")]
public ColorAdjustParticle[] ParticleObjs;
[Space(10)]
[Tooltip("Particle systems that will be affected by this color module")]
public ColorAdjustMesh[] MeshObjs;
private List<Color32> MostUsedColors = new List<Color32>();
private ParticleSystem.MainModule[] ParticleColorModules;
private Material[] MeshMaterials;
public Color32 C1;
public Color32 C2;
public float Saturation = 1.2f;
public float Value = 2f;
// Use this for initialization
void Start()
{
//SetColors();
}
public void SetDominantColors(Color32 c1, Color32 c2)
{
C1 = c1;
C2 = c2;
SetColors();
}
void GetParticleModules()
{
//ParticleColorModules = new ParticleSystem.MainModule[ParticleObjs.Length];
List<ParticleSystem.MainModule> result = new List<ParticleSystem.MainModule>();
for (int i = 0; i < ParticleObjs.Length; i++)
{
GameObject obj = ParticleObjs[i].Obj;
if (obj)
{
result.Add(obj.GetComponent<ParticleSystem>().main);
}
}
ParticleColorModules = result.ToArray();
}
public void SetColors()
{
MeshMaterials = new Material[MeshObjs.Length];
for (int i = 0; i < MeshObjs.Length; i++)
{
GameObject obj = MeshObjs[i].Obj;
if (obj)
{
Renderer rend = obj.GetComponent<Renderer>();
MeshMaterials[i] = rend.sharedMaterial;
}
}
for (int i = 0; i < MeshMaterials.Length; i++)
{
Color adjustedC1 = SaturateAdjust(C1, Saturation, Value);
if (MeshMaterials[i] != null)
{
MeshMaterials[i].SetColor("_MasterColor", adjustedC1);
}
}
GetParticleModules();
for (int i = 0; i < ParticleColorModules.Length; i++)
{
Color adjustedC1 = SaturateAdjust(C1, Saturation, Value);
if (ParticleObjs[i].SingleColor)
{
ParticleColorModules[i].startColor = new ParticleSystem.MinMaxGradient(adjustedC1, adjustedC1); // random between 2 colors
continue;
}
Color adjustedC2 = SaturateAdjust(C2, Saturation, Value);
ParticleColorModules[i].startColor = new ParticleSystem.MinMaxGradient(adjustedC1, adjustedC2); // random between 2 colors
}
}
int DeRes(float val, int count)
{
int i = 0;
while (i < count)
{
val *= 0.5f;
i++;
}
return Mathf.RoundToInt(val);
}
private Color32[] GetPixels()
{
if (UseMipmap)
{
return TextureImg.GetPixels32(MipmapLevel); // at mipmap level %
}
else
{
//TextureImg.GetPixel(1, 2);
return new Color32[10]; // TODO : return randomized picked from texture 60~100 and get 2 dominant colors - not yet ready
}
}
public void GetDominantColors()
{
int width = TextureImg.width;
int height = TextureImg.height;
Color32[] Colors;
Colors = GetPixels();
if (MipmapLevel > 0)
{
width = DeRes(width, MipmapLevel + 1);
height = DeRes(height, MipmapLevel + 1);
}
// does using Dictionary<Color,int> here
// really pay-off compared to using
// Dictionary<Color, int> ?
// would using a SortedDictionary be much slower, or ?
Dictionary<Color32, int> dctColorIncidence = new Dictionary<Color32, int>();
Color32 pixelColor;
for (int row = 0; row < width; row++)
{
for (int col = 0; col < height; col++)
{
int index = row * 10 + col;
pixelColor = Colors[index]; // divide by 8 to cluster better
if (pixelColor.a < 0.01f)
continue;
pixelColor.r /= 8;
pixelColor.g /= 8;
pixelColor.b /= 8;
if (dctColorIncidence.Keys.Contains(pixelColor))
{
dctColorIncidence[pixelColor]++;
}
else
{
dctColorIncidence.Add(pixelColor, 1);
}
}
}
// note that there are those who argue that a
// .NET Generic Dictionary is never guaranteed
// to be sorted by methods like this
var dctSortedByValueHighToLow = dctColorIncidence.OrderByDescending(x => x.Value).ToDictionary(x => x.Key, x => x.Value);
// this should be replaced with some elegant Linq ?
MostUsedColors.Clear();
foreach (KeyValuePair<Color32, int> kvp in dctSortedByValueHighToLow.Take(2))
{
Color32 c = kvp.Key;
MostUsedColors.Add(c);
}
}
Color32 SaturateAdjust(Color32 color, float saturation, float value)
{
float H;
float S;
float V;
Color.RGBToHSV(color, out H, out S, out V);
S *= saturation;
V *= value;
return Color.HSVToRGB(H, S, V);
}
}