private static SolidBrush GetFaceBrush(Prim prim, uint face) { // Block sillyness that would cause an exception. if (face >= Primitive.TextureEntry.MAX_FACES) { return(DefaultBrush); } var textures = new Primitive.TextureEntry(prim.Texture, 0, prim.Texture.Length); var facetexture = textures.GetFace(face); // GetFace throws a generic exception if the parameter is greater than MAX_FACES. // Compute a color from the texture data AND the color applied. The operation is "Multiplication" aka per-pixel (A*B)/255 or if float in domain 0-1: (A*B) Texture texture = null; try { texture = Texture.GetByUUID(facetexture.TextureID.Guid); } catch (Exception e) { var location = prim.ComputeWorldPosition(); LOG.Warn($"Error decoding image asset {facetexture.TextureID} on face {face} of prim {prim.Id} named '{prim.Name}' at {location} in region {prim.RegionId}, continuing using default texture.", e); } if (texture == null) { texture = Texture.DEFAULT; } return(new SolidBrush(Color.FromArgb( Math.Max(0, Math.Min(255, (int)(facetexture.RGBA.R * 255f) * texture.AverageColor.R / 255)), Math.Max(0, Math.Min(255, (int)(facetexture.RGBA.G * 255f) * texture.AverageColor.G / 255)), Math.Max(0, Math.Min(255, (int)(facetexture.RGBA.B * 255f) * texture.AverageColor.B / 255)) ))); // FromARGB can throw an exception if a parameter is outside 0-255, but that is prevented. }