public Texture2D SetupTextureAtlas(GraphicsDevice graphicsDevice) { var triangles = Models.SelectMany(m => m.ModelTriangles).ToList(); var dict = new Dictionary <KeyValuePair <string, Rectangle>, TrianglesWithCroppedTexture>(); foreach (var triangle in triangles) { if (!dict.ContainsKey(triangle.TextureKey)) { if (!TextureHandler.HasCroppedTexture(triangle.TextureKey)) { TextureHandler.AddCroppedTexture(triangle.TextureKey, TextureHandler.CropTexture(triangle.OriginalTexture, triangle.OriginalTextureRectangle)); } dict.Add(triangle.TextureKey, new TrianglesWithCroppedTexture() { CroppedTexture = TextureHandler.GetCroppedTexture(triangle.TextureKey).Key, HasTransparentPixels = TextureHandler.GetCroppedTexture(triangle.TextureKey).Value }); } dict[triangle.TextureKey].ModelTriangles.Add(triangle); } var packer = new RectanglePacker(4096, 4096); foreach (var pair in dict) { var rect = pair.Value.CroppedTexture.Bounds; if (!packer.Pack(rect.Width, rect.Height, out rect.X, out rect.Y)) { throw new Exception("Uh oh, we couldn't pack the rectangles"); } pair.Value.AtlasRectangle = rect; } foreach (var pair in dict) { foreach (var triangle in pair.Value.ModelTriangles) { triangle.AtlasTextureRectangle = pair.Value.AtlasRectangle; triangle.HasTransparentPixels = pair.Value.HasTransparentPixels; } } var atlas = new Texture2D(graphicsDevice, 4096, 4096); foreach (var pair in dict) { var data = new Color[pair.Value.CroppedTexture.Width * pair.Value.CroppedTexture.Height]; pair.Value.CroppedTexture.GetData(0, pair.Value.CroppedTexture.Bounds, data, 0, data.Length); atlas.SetData(0, pair.Value.AtlasRectangle, data, 0, data.Length); pair.Value.CroppedTexture = null; } return(atlas); }