void PushBlockReferenceData(ref List <float> referenceData, RawTexContainer layer, uint tx, uint ty, uint xBlock, uint yBlock) { for (uint j = 0; j < 4; j++) { for (uint i = 0; i < 4; i++) { uint px = (xBlock * 4 + i); uint py = (yBlock * 4 + j); float v = Convert.ToSingle(layer.tiles[Convert.ToInt32(tx + ty * layer._widthInTiles0)]._atlasUnCompressed[px + py * mlmask._atlasTileSize]) / 255.0f; referenceData.Add(v); } } }
private void PushBlockReferenceData(ref List <float> referenceData, RawTexContainer layer, uint tx, uint ty, uint xBlock, uint yBlock) { for (uint j = 0; j < 4; j++) { for (uint i = 0; i < 4; i++) { var px = (xBlock * 4) + i; var py = (yBlock * 4) + j; var v = Convert.ToSingle(layer.Tiles[Convert.ToInt32(tx + (ty * layer.WidthInTiles0))].AtlasUnCompressed[px + (py * _mlmask.AtlasTileSize)]) / 255.0f; referenceData.Add(v); } } }
void CreateAtlasBuffer() { if (mlmask._atlasWidth <= 0 || mlmask._atlasHeight <= 0) { throw new Exception("Unable to generate MLmask atlas data"); } uint tileSizeInBlocks0 = mlmask._atlasTileSize / 4; uint WidthInBlocks0 = mlmask._atlasWidth / 4; uint HeightInBlocks0 = mlmask._atlasHeight / 4; uint WidthInTiles0 = mlmask._atlasWidth / mlmask._atlasTileSize; var Data = new UInt64[(WidthInBlocks0 * HeightInBlocks0)]; foreach (var atlasTile in mlmask._atlasTiles.Values) { RawTexContainer sourceLayer = mlmask.layers[atlasTile._layerIndex]; Tile tileSource = sourceLayer.tiles[Convert.ToInt32(atlasTile._layerTileIndex)]; uint position = atlasTile._atlasInPosition; uint tx = position % WidthInTiles0; uint ty = position / WidthInTiles0; uint bx = tx * tileSizeInBlocks0; uint by = ty * tileSizeInBlocks0; uint destinationIdx = bx + by * WidthInBlocks0; for (uint i = 0; i < tileSizeInBlocks0; i++) { Array.Copy(tileSource._atlasBlockCompressed, i * tileSizeInBlocks0, Data, destinationIdx, tileSizeInBlocks0); destinationIdx += WidthInBlocks0; } } MemoryStream ms = new MemoryStream(); BinaryWriter bw = new BinaryWriter(ms); for (int i = 0; i < Data.Length; i++) { bw.Write(Data[i]); } mlmask._AtlasBuffer = ms.ToArray(); }
void BlockCompressLocalTile(ref RawTexContainer layer, uint tileIdx) { uint tileSizeInBlocks0 = mlmask._atlasTileSize / 4; uint tx = (tileIdx % layer._widthInTiles0); uint ty = (tileIdx / layer._widthInTiles0); var layerTile = layer.tiles[Convert.ToInt32(tileIdx)]; layerTile._atlasBlockCompressed = new UInt64[(tileSizeInBlocks0 * tileSizeInBlocks0)]; for (uint yBlock = 0; yBlock < tileSizeInBlocks0; yBlock++) { for (uint xBlock = 0; xBlock < tileSizeInBlocks0; xBlock++) { List <float> referenceData = new List <float>(); float[] toBBCValues = new float[16]; for (uint j = 0; j < 4; j++) { for (uint i = 0; i < 4; i++) { uint px = xBlock * 4 + i; uint py = yBlock * 4 + j; float v = Convert.ToSingle(layerTile._atlasUnCompressed[px + py * mlmask._atlasTileSize]) / 255.0f; toBBCValues[i + j * 4] = v; referenceData.Add(v); } } if ((tx > 0) && (xBlock == 0)) { PushBlockReferenceData(ref referenceData, layer, tx - 1, ty, tileSizeInBlocks0 - 1, yBlock); } else if ((tx < layer._widthInTiles0 - 1) && (xBlock == tileSizeInBlocks0 - 1)) { PushBlockReferenceData(ref referenceData, layer, tx + 1, ty, 0, yBlock); } if ((ty > 0) && (yBlock == 0)) { PushBlockReferenceData(ref referenceData, layer, tx, ty - 1, xBlock, tileSizeInBlocks0 - 1); } else if ((ty < layer._heightInTiles0 - 1) && (yBlock == tileSizeInBlocks0 - 1)) { PushBlockReferenceData(ref referenceData, layer, tx, ty + 1, xBlock, 0); } if (((tx > 0) && (xBlock == 0)) && ((ty > 0) && (yBlock == 0))) { PushBlockReferenceData(ref referenceData, layer, tx - 1, ty - 1, tileSizeInBlocks0 - 1, tileSizeInBlocks0 - 1); } else if (((tx < layer._widthInTiles0 - 1) && (xBlock == tileSizeInBlocks0 - 1)) && ((ty > 0) && (yBlock == 0))) { PushBlockReferenceData(ref referenceData, layer, tx + 1, ty - 1, 0, tileSizeInBlocks0 - 1); } else if (((tx > 0) && (xBlock == 0)) && ((ty < layer._heightInTiles0 - 1) && (yBlock == tileSizeInBlocks0 - 1))) { PushBlockReferenceData(ref referenceData, layer, tx - 1, ty + 1, tileSizeInBlocks0 - 1, 0); } else if (((tx < layer._widthInTiles0 - 1) && (xBlock == tileSizeInBlocks0 - 1)) && ((ty < layer._heightInTiles0 - 1) && (yBlock == tileSizeInBlocks0 - 1))) { PushBlockReferenceData(ref referenceData, layer, tx + 1, ty + 1, 0, 0); } UInt64 blockCompressed = 0; D3DX.D3DXEncodeBC4U(ref blockCompressed, toBBCValues, referenceData); layerTile._atlasBlockCompressed[xBlock + yBlock * tileSizeInBlocks0] = blockCompressed; } } layer.tiles[Convert.ToInt32(tileIdx)] = layerTile; }
public void Import(FileInfo txtimageList, FileInfo outFile) { var files = File.ReadAllLines(txtimageList.FullName); #region InitandVerify mlmask = new MLMaskContainer(); List <RawTexContainer> textures = new List <RawTexContainer>(); RawTexContainer white = new RawTexContainer(); white._pixels = new Byte[16]; Array.Fill <Byte>(white._pixels, 255); white._width = 4; white._height = 4; textures.Add(white); int lineIdx = 1; foreach (var f in files) { if (!File.Exists(f)) { throw new FileNotFoundException($"Line{{lineIdx}}: \"{f}\" Make sure the file path is valid and exists (paths are specified line by line in ascending layer order in masklist)"); } var ms = new MemoryStream(File.ReadAllBytes(f)); var s = Path.GetExtension(f).ToLower(); var euncook = Enum.Parse <EUncookExtension>(Path.GetExtension(f).ToLower().Replace(".", "")); if (euncook != EUncookExtension.dds) { ms = new MemoryStream(DDSUtils.ConvertToDdsMemory(ms, euncook, DXGI_FORMAT.DXGI_FORMAT_R8_UNORM)); } else { // why dds to dds?, to make sure format is r8_unorm ms = new MemoryStream(DDSUtils.ConvertToDdsMemory(new MemoryStream(DDSUtils.ConvertFromDdsMemory(ms, EUncookExtension.tga)), EUncookExtension.tga, DXGI_FORMAT.DXGI_FORMAT_R8_UNORM)); } ms.Seek(0, SeekOrigin.Begin); DDS_HEADER header; DDSUtils.TryReadDdsHeader(ms, out header); if (header.dwWidth != header.dwHeight) { throw new Exception($"Texture {f}: width={header.dwWidth},height={header.dwHeight} must have an aspect ratio of 1:1"); } // One bitset check if ((((header.dwWidth - 1) & header.dwHeight) != 0) || (header.dwWidth == 0)) { throw new Exception($"Texture {f}: width={header.dwWidth},height={header.dwHeight} must have dimensions in powers of 2"); } //if (header.dwMipMapCount > 1) // throw new Exception($"Texture {f}: Mipmaps={header.dwMipMapCount}, mimap count must be equal to 1"); //if ((ms.Length - headerLength) != (header.dwWidth * header.dwHeight)) // throw new Exception("Not R8_UNORM 8bpp image format or more than 1mipmaps or rowstride is not equal to width or its a dx10 dds(unsupported)"); var br = new BinaryReader(ms); ms.Seek(headerLength, SeekOrigin.Begin); Byte[] bytes = br.ReadBytes((int)(header.dwWidth * header.dwHeight)); bool whiteCheck = true; for (int i = 0; i < bytes.Length; i++) { if (bytes[i] != 255) { whiteCheck = false; break; } } if (whiteCheck) { throw new Exception("No need to provide the 1st/any blank white mask layer, tool will generate 1st blank white layer automatically"); } RawTexContainer tex = new RawTexContainer(); tex._width = header.dwWidth; tex._height = header.dwHeight; tex._pixels = bytes; textures.Add(tex); lineIdx++; } mlmask.layers = textures.ToArray(); #endregion Create(); Write(outFile); }
private void BlockCompressLocalTile(ref RawTexContainer layer, uint tileIdx) { var tileSizeInBlocks0 = _mlmask.AtlasTileSize / 4; var tx = tileIdx % layer.WidthInTiles0; var ty = tileIdx / layer.WidthInTiles0; var layerTile = layer.Tiles[Convert.ToInt32(tileIdx)]; layerTile.AtlasBlockCompressed = new ulong[tileSizeInBlocks0 * tileSizeInBlocks0]; for (uint yBlock = 0; yBlock < tileSizeInBlocks0; yBlock++) { for (uint xBlock = 0; xBlock < tileSizeInBlocks0; xBlock++) { var referenceData = new List <float>(); var toBBCValues = new float[16]; for (uint j = 0; j < 4; j++) { for (uint i = 0; i < 4; i++) { var px = (xBlock * 4) + i; var py = (yBlock * 4) + j; var v = Convert.ToSingle(layerTile.AtlasUnCompressed[px + (py * _mlmask.AtlasTileSize)]) / 255.0f; toBBCValues[i + (j * 4)] = v; referenceData.Add(v); } } if (tx > 0 && xBlock == 0) { PushBlockReferenceData(ref referenceData, layer, tx - 1, ty, tileSizeInBlocks0 - 1, yBlock); } else if (tx < layer.WidthInTiles0 - 1 && xBlock == tileSizeInBlocks0 - 1) { PushBlockReferenceData(ref referenceData, layer, tx + 1, ty, 0, yBlock); } if (ty > 0 && yBlock == 0) { PushBlockReferenceData(ref referenceData, layer, tx, ty - 1, xBlock, tileSizeInBlocks0 - 1); } else if (ty < layer.HeightInTiles0 - 1 && yBlock == tileSizeInBlocks0 - 1) { PushBlockReferenceData(ref referenceData, layer, tx, ty + 1, xBlock, 0); } if (tx > 0 && xBlock == 0 && ty > 0 && yBlock == 0) { PushBlockReferenceData(ref referenceData, layer, tx - 1, ty - 1, tileSizeInBlocks0 - 1, tileSizeInBlocks0 - 1); } else if (tx < layer.WidthInTiles0 - 1 && xBlock == tileSizeInBlocks0 - 1 && ty > 0 && yBlock == 0) { PushBlockReferenceData(ref referenceData, layer, tx + 1, ty - 1, 0, tileSizeInBlocks0 - 1); } else if (tx > 0 && xBlock == 0 && ty < layer.HeightInTiles0 - 1 && yBlock == tileSizeInBlocks0 - 1) { PushBlockReferenceData(ref referenceData, layer, tx - 1, ty + 1, tileSizeInBlocks0 - 1, 0); } else if (tx < layer.WidthInTiles0 - 1 && xBlock == tileSizeInBlocks0 - 1 && ty < layer.HeightInTiles0 - 1 && yBlock == tileSizeInBlocks0 - 1) { PushBlockReferenceData(ref referenceData, layer, tx + 1, ty + 1, 0, 0); } ulong blockCompressed = 0; D3DX.D3DXEncodeBC4U(ref blockCompressed, toBBCValues, referenceData); layerTile.AtlasBlockCompressed[xBlock + (yBlock * tileSizeInBlocks0)] = blockCompressed; } } layer.Tiles[Convert.ToInt32(tileIdx)] = layerTile; }