public AtlasNode Insert(Image surface) { if (left != null) { AtlasNode rv; if (right == null) { throw new InvalidOperationException("AtlasNode(): error"); } rv = left.Insert(surface); if (rv == null) { rv = right.Insert(surface); } return(rv); } int img_width = surface.Width + padding * 2; int img_height = surface.Height + padding * 2; if (in_use || img_width > width || img_height > height) { return(null); } if (img_width == width && img_height == height) { in_use = true; tex = surface; return(this); } if (width - img_width > height - img_height) { /* extend to the right */ left = new AtlasNode(x, y, img_width, height, padding); right = new AtlasNode(x + img_width, y, width - img_width, height, padding); } else { /* extend to bottom */ left = new AtlasNode(x, y, width, img_height, padding); right = new AtlasNode(x, y + img_height, width, height - img_height, padding); } return(left.Insert(surface)); }
public TextureAtlas(BitmapSurface[] surfaces) { AtlasNode root = new AtlasNode(); root.Rectangle = new Rect(0, 0, 512, 512); _packedTextureRects = new Rect[surfaces.Length]; for (int i = 0; i < surfaces.Length; i++) { root.Insert(surfaces[i], i); } load(root); }
public TextureAtlas(TextureResource[] textures) { // heavily based on // http://www.blackpawn.com/texts/lightmaps/default.html // basically it uses a kd-tree to pack the lightmaps AtlasNode root = new AtlasNode(); root.Rectangle = new Rect(0, 0, 512, 512); _packedTextureRects = new Rect[textures.Length]; for (int i = 0; i < textures.Length; i++) { root.Insert(new BitmapSurface(textures[i]), i); } load(root); }
/// <summary> /// /// </summary> /// <param name="buildContext"></param> public override void Build(BuildContext buildContext) { var fileNames = buildContext.ExpandAndResolveSearchPatterns(Dependencies); var images = fileNames .Select(fn => Image.LoadTga(fn)) .OrderByDescending(img0 => img0.Width * img0.Height) .ThenByDescending(img1 => img1.Width) .ThenByDescending(img2 => img2.Height) .ToList(); if (!images.Any()) { throw new InvalidOperationException("At least one subimage must be added to teh texture atlas"); } // // Pack atlas : // AtlasNode root = new AtlasNode(0, 0, Width, Height, Padding); foreach (var img in images) { var n = root.Insert(img); if (n == null) { throw new InvalidOperationException("No enough room to place image"); } } // // Create image and fill it with atlas elements : // var targetImage = new Image(Width, Height); targetImage.Fill(FillColor); root.WriteImages(targetImage); // // Save and compress : // var tgaOutput = buildContext.GetTempFileName(AssetPath, ".tga", true); var ddsOutput = buildContext.GetTempFileName(AssetPath, ".dds", true); Image.SaveTga(targetImage, tgaOutput); var compression = UseDXT ? ImageFileTextureAsset.TextureCompression.BC3 : ImageFileTextureAsset.TextureCompression.RGB; ImageFileTextureAsset.RunNVCompress(buildContext, tgaOutput, ddsOutput, NoMips, false, false, true, true, false, compression); // // Write binary blob (text + dds texture): // using (var fs = buildContext.TargetStream(this)) { var bw = new BinaryWriter(fs); bw.Write(new[] { 'A', 'T', 'L', 'S' }); bw.Write(images.Count); root.WriteLayout(bw); bw.Write((int)(new FileInfo(ddsOutput).Length)); using (var dds = File.OpenRead(ddsOutput)) { dds.CopyTo(fs); } } }
/// <summary> /// /// </summary> /// <param name="buildContext"></param> public override void Process ( AssetSource assetFile, BuildContext context ) { var fileDir = Path.GetDirectoryName( assetFile.FullSourcePath ); var fileNames = File.ReadAllLines(assetFile.FullSourcePath) .Select( f1 => f1.Trim() ) .Where( f2 => !f2.StartsWith("#") && !string.IsNullOrWhiteSpace(f2) ) .Select( f3 => Path.Combine( fileDir, f3 ) ) .ToArray(); var depNames = File.ReadAllLines(assetFile.FullSourcePath) .Select( f1 => f1.Trim() ) .Where( f2 => !f2.StartsWith("#") && !string.IsNullOrWhiteSpace(f2) ) .Select( f3 => Path.Combine( Path.GetDirectoryName(assetFile.KeyPath), f3 ) ) .ToArray(); var images = fileNames .Select( fn => LoadImage( fn ) ) .OrderByDescending( img0 => img0.Width * img0.Height ) .ThenByDescending( img1 => img1.Width ) .ThenByDescending( img2 => img2.Height ) .ToList(); if (!images.Any()) { throw new InvalidOperationException("At least one subimage must be added to the texture atlas"); } // // Pack atlas : // AtlasNode root = new AtlasNode(0,0, Width, Height, Padding ); foreach ( var img in images ) { var n = root.Insert( img ); if (n==null) { throw new InvalidOperationException("No enough room to place image"); } } // // Create image and fill it with atlas elements : // var targetImage = new Image( Width, Height ); targetImage.Fill( FillColor ); root.WriteImages( targetImage ); // // Save and compress : // var tgaOutput = context.GetTempFileName( assetFile.KeyPath, ".tga" ); var ddsOutput = context.GetTempFileName( assetFile.KeyPath, ".dds" ); Image.SaveTga( targetImage, tgaOutput ); var compression = UseDXT ? TextureProcessor.TextureCompression.BC3 : TextureProcessor.TextureCompression.RGB; TextureProcessor.RunNVCompress( context, tgaOutput, ddsOutput, NoMips, false, false, true, true, false, compression ); // // Write binary blob (text + dds texture): // using ( var fs = assetFile.OpenTargetStream(depNames) ) { var bw = new BinaryWriter( fs ); bw.Write(new[]{'A','T','L','S'}); bw.Write( images.Count ); root.WriteLayout( bw ); bw.Write( (int)(new FileInfo(ddsOutput).Length) ); using ( var dds = File.OpenRead( ddsOutput ) ) { dds.CopyTo( fs ); } } }
/// <summary> /// /// </summary> /// <param name="buildContext"></param> public override void Build ( BuildContext buildContext ) { var fileNames = buildContext.ExpandAndResolveSearchPatterns( Dependencies ); var images = fileNames .Select( fn => Image.LoadTga( fn ) ) .OrderByDescending( img0 => img0.Width * img0.Height ) .ThenByDescending( img1 => img1.Width ) .ThenByDescending( img2 => img2.Height ) .ToList(); if (!images.Any()) { throw new InvalidOperationException("At least one subimage must be added to teh texture atlas"); } // // Pack atlas : // AtlasNode root = new AtlasNode(0,0, Width, Height, Padding ); foreach ( var img in images ) { var n = root.Insert( img ); if (n==null) { throw new InvalidOperationException("No enough room to place image"); } } // // Create image and fill it with atlas elements : // var targetImage = new Image( Width, Height ); targetImage.Fill( FillColor ); root.WriteImages( targetImage ); // // Save and compress : // var tgaOutput = buildContext.GetTempFileName( AssetPath, ".tga" ); var ddsOutput = buildContext.GetTempFileName( AssetPath, ".dds" ); Image.SaveTga( targetImage, tgaOutput ); var compression = UseDXT ? ImageFileTextureAsset.TextureCompression.BC3 : ImageFileTextureAsset.TextureCompression.RGB; ImageFileTextureAsset.RunNVCompress( buildContext, tgaOutput, ddsOutput, NoMips, false, false, true, true, false, compression ); // // Write binary blob (text + dds texture): // using ( var fs = buildContext.OpenTargetStream( this ) ) { var bw = new BinaryWriter( fs ); bw.Write(new[]{'A','T','L','S'}); bw.Write( images.Count ); root.WriteLayout( bw ); bw.Write( (int)(new FileInfo(ddsOutput).Length) ); using ( var dds = File.OpenRead( ddsOutput ) ) { dds.CopyTo( fs ); } } }
public AtlasNode Insert(BitmapSurface surface, int index) { AtlasNode newNode = null; if (Child1 != null && Child2 != null) { // not on a leaf... newNode = Child1.Insert(surface, index); if (newNode != null) { return(newNode); } // no room? try the other child... return(Child2.Insert(surface, index)); } else { // we're on a leaf! if (Surface != null) { return(null); } int fit = testFit(surface); if (fit > 0) { return(null); // too big } if (fit == 0) { Surface = surface; Index = index; return(this); } // guess we need to split this node Child1 = new AtlasNode(); Child2 = new AtlasNode(); int paddedWidth = surface.Width + Padding * 2; int paddedHeight = surface.Height + Padding * 2; float dw = Rectangle.Width - paddedWidth; float dh = Rectangle.Height - paddedHeight; if (dw > dh) { Child1.Rectangle = new Rect(Rectangle.X, Rectangle.Y, paddedWidth, Rectangle.Height); Child2.Rectangle = new Rect(Rectangle.X + paddedWidth + 1, Rectangle.Y, Rectangle.Width - paddedWidth - 1, Rectangle.Height); } else { Child1.Rectangle = new Rect(Rectangle.X, Rectangle.Y, Rectangle.Width, paddedHeight); Child2.Rectangle = new Rect(Rectangle.X, Rectangle.Y + paddedHeight + 1, Rectangle.Width, Rectangle.Height - paddedHeight - 1); } return(Child1.Insert(surface, index)); } }
/// <summary> /// /// </summary> /// <param name="buildContext"></param> public override void Process(AssetSource assetFile, BuildContext context) { var fileDir = Path.GetDirectoryName(assetFile.FullSourcePath); var fileNames = File.ReadAllLines(assetFile.FullSourcePath) .Select(f1 => f1.Trim()) .Where(f2 => !f2.StartsWith("#") && !string.IsNullOrWhiteSpace(f2)) .Select(f3 => Path.Combine(fileDir, f3)) .ToArray(); var depNames = File.ReadAllLines(assetFile.FullSourcePath) .Select(f1 => f1.Trim()) .Where(f2 => !f2.StartsWith("#") && !string.IsNullOrWhiteSpace(f2)) .Select(f3 => Path.Combine(Path.GetDirectoryName(assetFile.KeyPath), f3)) .ToArray(); var images = fileNames .Select(fn => LoadImage(fn)) .OrderByDescending(img0 => img0.Width * img0.Height) .ThenByDescending(img1 => img1.Width) .ThenByDescending(img2 => img2.Height) .ToList(); if (!images.Any()) { throw new InvalidOperationException("At least one subimage must be added to the texture atlas"); } // // Pack atlas : // AtlasNode root = new AtlasNode(0, 0, Width, Height, Padding); foreach (var img in images) { var n = root.Insert(img); if (n == null) { throw new InvalidOperationException("No enough room to place image"); } } // // Create image and fill it with atlas elements : // var targetImage = new Image(Width, Height); targetImage.Fill(FillColor); root.WriteImages(targetImage); // // Save and compress : // var tgaOutput = context.GetTempFileFullPath(assetFile.KeyPath, ".tga"); var ddsOutput = context.GetTempFileFullPath(assetFile.KeyPath, ".dds"); Image.SaveTga(targetImage, tgaOutput); var compression = UseDXT ? TextureProcessor.TextureCompression.BC3 : TextureProcessor.TextureCompression.RGB; TextureProcessor.RunNVCompress(context, tgaOutput, ddsOutput, NoMips, false, false, true, true, false, compression); // // Write binary blob (text + dds texture): // using (var fs = assetFile.OpenTargetStream(depNames)) { var bw = new BinaryWriter(fs); bw.Write(new[] { 'A', 'T', 'L', 'S' }); bw.Write(images.Count); root.WriteLayout(bw); bw.Write((int)(new FileInfo(ddsOutput).Length)); using (var dds = File.OpenRead(ddsOutput)) { dds.CopyTo(fs); } } }