- Home /
Show the percentage of painted surface on the wall
I want to show the percentage of painted surface on the wall. Here is the code I used to paint the wall.
private void MyPaintOn(Vector2 textureCoord, float[,] splashTexture, Color targetColor)
{
if (m_isEnabled)
{
lock (m_lockFlag)
{
Stopwatch sw = new Stopwatch();
sw.Start();
int reqnx = splashTexture.GetLength(0);
int reqny = splashTexture.GetLength(1);
int reqX = (int)(textureCoord.x * textureSize) - (reqnx / 2);
int reqY = (int)(textureCoord.y * textureSize) - (reqny / 2);
int right = m_texture.width - 1;
int bottom = m_texture.height - 1;
int x = IntMax(reqX, 0);
int y = IntMax(reqY, 0);
int nx = IntMin(x + reqnx, right) - x;
int ny = IntMin(y + reqny, bottom) - y;
Color[] pixels = m_texture.GetPixels(x, y, nx, ny);
int counter = 0;
for (int i = 0; i < nx; ++i)
{
for (int j = 0; j < ny; ++j)
{
float currAlpha = splashTexture[i, j];
if (currAlpha == 1)
pixels[counter] = targetColor;
else
{
Color currColor = pixels[counter];
// resulting color is an addition of splash texture to the texture based on alpha
Color newColor = Color.Lerp(currColor, targetColor, currAlpha);
// but resulting alpha is a sum of alphas (adding transparent color should not make base color more transparent)
newColor.a = pixels[counter].a + currAlpha;
pixels[counter] = newColor;
}
counter++;
}
m_texture.SetPixels(x, y, nx, ny, pixels);
m_texture.Apply();
sw.Stop();
}
}
}
}
btw. remove that lock
mate, it encapsulates exclusively main-thread code there (`m_texture.`).
Answer by andrew-lukasik · Mar 05, 2021 at 12:52 PM
You can calculate color fill and overall similarity values by treating colors as n-dimensional vectors inside a unit cube (or equivalent). This enables you to express color differences with a single numerical value - distance between them.
static float CalculateFill ( Color[] colors , Color reference , float tolerance )
{
Vector3 target = new Vector3{ x=reference.r , y=reference.g , z=reference.b };
int numHits = 0;
const float sqrt_3 = 1.73205080757f;
for( int i=0 ; i<colors.Length ; i++ )
{
Vector3 next = new Vector3{ x=colors[i].r , y=colors[i].g , z=colors[i].b };
float mag = Vector3.Magnitude( target - next ) / sqrt_3;
numHits += mag<=tolerance ? 1 : 0;
}
return (float)numHits / (float)colors.Length;;
}
static float CalculateSimilarity ( Color[] colors , Color reference )
{
Vector3 target = new Vector3{ x=reference.r , y=reference.g , z=reference.b };
float accu = 0;
const float sqrt_3 = 1.73205080757f;
for( int i=0 ; i<colors.Length ; i++ )
{
Vector3 next = new Vector3{ x=colors[i].r , y=colors[i].g , z=colors[i].b };
accu += Vector3.Magnitude( target - next ) / sqrt_3;
}
return 1f - ( (float)accu / (float)colors.Length );
}
I'm sure you can simplify this further to meet your project requirements. Optimizing this for runtime-use is whole another topic.
Here is a full source for an editor tool to check how well it works. Some test results:
Hi andrew, Can you explain what is the importance of sqrt 3 in this equation? I couldn't find an answer on google.
Hi. Sure, sqrt_3
represents diagonal of a unit cube
. Removing it will introduce a variable margin of error as it is used to normalize the results.
Google may not help much as this method is something I came up with here on the spot.
Thanks, I got it now! This doesn't fell like you came up on spot, it's working nicely! Btw, For me 0.5 was satisfactory for tolerance value.