public TAMImageDiagram Generate(TAMImageDiagram baseDiagram, TAMTone tone, TAMMipmapLevel mipmapLevel, int seed) { _strokesGenerator.ResetSeed(seed); _random = new System.Random(seed); var diagram = baseDiagram.Copy(); float currentCoverage = ComputeCoverage(diagram, mipmapLevel); float targetCoverage = _generationConfiguration.TargetCoverages[tone]; while (targetCoverage > currentCoverage) { List <RankedPossibleStroke> possibleStrokes = new List <RankedPossibleStroke>(); for (int i = 0; i < _generationConfiguration.TriesCount[mipmapLevel]; i++) { TAMStroke newStroke = _strokesGenerator.CreateRandomStroke(new Vector2(_random.Next(), _random.Next()), tone); RankedPossibleStroke rankedNewStroke = RankStroke(newStroke, diagram); possibleStrokes.Add(rankedNewStroke); } var bestStroke = possibleStrokes.OrderBy(p => p.Rank).First(); diagram.AddStroke(bestStroke.Stroke); currentCoverage = ComputeCoverage(diagram, mipmapLevel); } return(diagram); }
public void Start0() { var tonesCount = 5; var levelsCount = 5; TaskUtils.SetGlobalMultithreading(false); var tones = TAMTone.CreateList(tonesCount, new Dictionary <int, TAMStrokeOrientation>() { { 0, TAMStrokeOrientation.Horizontal }, { 3, TAMStrokeOrientation.Vertical }, { 5, TAMStrokeOrientation.Both } }); var levels = TAMMipmapLevel.CreateList(levelsCount); var fileManager = new TAMPackFileManager(); var soleImagesPack = fileManager.Load(@"C:\mgr\tmp\tam1\", tones, levels); var generator = new TAMArrayGenerator(); var tex2DArray = generator.Generate(soleImagesPack, tones, levels); var go = GameObject.CreatePrimitive(PrimitiveType.Plane); var material = new Material(Shader.Find("Custom/Debug/TextureArrayLod")); material.SetTexture("_MainTex", tex2DArray); go.GetComponent <MeshRenderer>().material = material; MyAssetDatabase.CreateAndSaveAsset(tex2DArray, "Assets/Generated/TAM1.asset"); }
public TAMStroke UpdatePerMipmapLevelStrokeParameters(TAMStroke tamStroke, TAMMipmapLevel level) { var reverseIndex = level.MipmapLevelsCount - level.LevelIndex - 1; var newHeight = tamStroke.Height * Mathf.Pow(_generationConfiguration.PerMipmapLevelHeightMultiplier, reverseIndex); return(new TAMStroke(tamStroke.Center, newHeight, tamStroke.Length, tamStroke.Rotation, tamStroke.Id)); }
public TAMImageDiagram Generate(TAMImageDiagram diagram, TAMTone tone, TAMMipmapLevel mipmapLevel, int seed) { List <Vector2> currentPoints = diagram.Strokes.Select(c => c.Center).ToList(); var newPoints = _sampler.Generate(_configuration.GenerationCount, _configuration.ExclusionZoneValues[tone][mipmapLevel], seed, currentPoints); return(new TAMImageDiagram(diagram.Strokes.Union(newPoints.Select(c => _strokesGenerator.CreateRandomStroke(c, tone))).ToList())); }
private TAMImageDiagram GetPreviousToneImageDiagram(TAMTone tone, TAMMipmapLevel mipmapLevel) { if (tone.IsLowestTone) { return(TAMImageDiagram.CreateEmpty()); } else { return(_columns[tone.LowerTone][mipmapLevel]); } }
public static List <TAMMipmapLevel> CreateList(int count) { var outList = new List <TAMMipmapLevel>(); TAMMipmapLevel lastMipmapLevel = null; for (int i = 0; i < count; i++) { var newMipmapLevel = new TAMMipmapLevel(i, count, lastMipmapLevel); outList.Add(newMipmapLevel); lastMipmapLevel = newMipmapLevel; } return(outList); }
private Image CreateSoleImage(TAMImageDiagram diagram, TAMMipmapLevel level) { var margin = _configuration.Margin; var soleImageResolution = _configuration.SoleImagesResolutionPerLevel[level].ToFloatVec(); var soleImageResolutionWithMargins = soleImageResolution * (1 + margin * 2); using (ImageFactory imageFactory = new ImageFactory(preserveExifData: true)) { var factory = imageFactory.Load(_blankImage) .Resize(new Size((int)soleImageResolutionWithMargins.x, (int)soleImageResolutionWithMargins.y)); foreach (var stroke in diagram.Strokes) { using (ImageFactory strokeFactory = new ImageFactory(true)) { var strokeSizeInPixels = VectorUtils.MemberwiseMultiply( new Vector2(stroke.Length, stroke.Height * _configuration.StrokeHeightMultiplierPerLevel[level]), soleImageResolution).ToIntVector2(); var rotation = Mathf.Rad2Deg * stroke.Rotation; var rotatedStrokeImageFactory = strokeFactory.Load(_strokeImage) .Resize(new ResizeLayer(new Size(strokeSizeInPixels.X, strokeSizeInPixels.Y), ResizeMode.Stretch)) .Rotate(rotation); //if (stroke.Id == 1) //{ // rotatedStrokeImageFactory = rotatedStrokeImageFactory.ReplaceColor(Color.Black, Color.Blue); //} var rotatedStrokeImage = rotatedStrokeImageFactory.Image; var position = VectorUtils.MemberwiseMultiply(UvToMarginUv(stroke.Center), soleImageResolutionWithMargins).ToIntVector2(); //todo przelicz tu aby brac pod uwage multiplier position -= new IntVector2(rotatedStrokeImage.Width / 2, rotatedStrokeImage.Height / 2); factory = factory.Overlay(new ImageLayer() { Image = rotatedStrokeImage, Opacity = 100, Position = new Point(position.X, position.Y) }); } } using (Stream stream = new MemoryStream()) { factory.Save(stream); return(Image.FromStream(stream)); } } }
private float ComputeCoverage(TAMImageDiagram diagram, TAMMipmapLevel mipmapLevel) { var areaSum = 0.0; for (int i = 0; i < diagram.Strokes.Count; i++) { var currentStroke = diagram.Strokes[i]; var baseArea = Mathf.PI * Mathf.Pow(currentStroke.Length, 2) * 0.2; //todo for (int k = 0; k < i; k++) { var otherStroke = diagram.Strokes[k]; var intersectionArea = MyMathUtils.IntersectionAreaOfTwoCircles(currentStroke.Length, currentStroke.Center, otherStroke.Length, otherStroke.Center); baseArea -= intersectionArea; } areaSum += Math.Max(0.001f, baseArea); //todo what to do with other mipmapLevels } return((float)areaSum); }
public void StartDiagram() { var tonesCount = 4; var levelsCount = 4; TaskUtils.SetGlobalMultithreading(false); var tones = TAMTone.GenerateList(tonesCount, 3, 4); var levels = TAMMipmapLevel.CreateList(levelsCount); var tamPackGenerator = new TAMPackGenerator(); var msw = new MyStopWatch(); msw.StartSegment("Gen"); var pack = tamPackGenerator.GenerateTamPack(GenerateDiagramConfiguration(tones, levels, 0.7f), true, Object.FindObjectOfType <ComputeShaderContainerGameObject>()); Debug.Log(msw.CollectResults()); var fileManager = new TAMPackFileManager(); fileManager.Save(@"C:\mgr\tmp\tam2\", tones, levels, pack); }
public TAMImageDiagram UpdatePerMipmapLevelStrokeParameters(TAMImageDiagram diagram, TAMMipmapLevel level) { return(new TAMImageDiagram(diagram.Strokes.Select(c => _strokesGenerator.UpdatePerMipmapLevelStrokeParameters(c, level)).ToList())); }
public TAMMipmapLevel(int levelIndex, int mipmapLevelsCount, TAMMipmapLevel lowerLevel = null) { _levelIndex = levelIndex; _lowerLevel = lowerLevel; _mipmapLevelsCount = mipmapLevelsCount; }
private void AddNewImageDiagram(TAMImageDiagram template, TAMTone tone, TAMMipmapLevel mipmapLevel) { _columns[tone][mipmapLevel] = template; }
private TAMImageDiagram GenerateNewImageDiagram(TAMImageDiagram baseImageDiagram, TAMTone tone, TAMMipmapLevel mipmapLevel, int seed) { return(_imageDiagramGenerator.Generate(baseImageDiagram, tone, mipmapLevel, seed)); }
private List <Image> CreateSoleLayerImages(TAMImageDiagram diagram, TAMMipmapLevel level) { var margin = _configuration.Margin; var soleImageResolution = _configuration.SoleImagesResolutionPerLevel[level]; var soleImageResolutionWithMargins = (soleImageResolution * (1 + margin * 2)).ToIntVector2(); var marginLength = (soleImageResolutionWithMargins - soleImageResolution) / 2; var outImages = Enumerable.Range(0, _layersCount) .Select(c => new Bitmap((int)soleImageResolutionWithMargins.X, (int)soleImageResolutionWithMargins.Y, PixelFormat.Format32bppPArgb)) .ToList(); var occupancyArray = new int[(int)soleImageResolutionWithMargins.X, (int)soleImageResolutionWithMargins.Y]; //Debug.Log($"OutiMages: {outImages[0].Size} || SoleImageResolution {soleImageResolution} Sole with margins {soleImageResolutionWithMargins}"); foreach (var stroke in diagram.Strokes) { using (ImageFactory strokeFactory = new ImageFactory(true)) { var strokeSizeInPixels = VectorUtils.MemberwiseMultiply( new Vector2(stroke.Length, stroke.Height * _configuration.StrokeHeightMultiplierPerLevel[level]), soleImageResolution.ToFloatVec()).ToIntVector2(); var rotation = Mathf.Rad2Deg * stroke.Rotation; var rotatedStrokeImage = strokeFactory.Load(_strokeImage) .Resize(new ResizeLayer(new Size(strokeSizeInPixels.X, strokeSizeInPixels.Y), ResizeMode.Stretch)) .Rotate(rotation).Image; var imageWithId = AddIdToStrokeImage(rotatedStrokeImage, (uint)stroke.Id); var position = VectorUtils.MemberwiseMultiply(UvToMarginUv(stroke.Center), soleImageResolutionWithMargins.ToFloatVec()).ToIntVector2(); position -= new IntVector2(rotatedStrokeImage.Width / 2, rotatedStrokeImage.Height / 2); for (int x = 0; x < imageWithId.Size.Width; x++) { for (int y = 0; y < imageWithId.Size.Height; y++) { var inImagePosition = position + new IntVector2(x, y); uint offsetBitX = 0; uint offsetBitY = 0; if (inImagePosition.X - marginLength.X / 2 >= soleImageResolution.X || inImagePosition.X - marginLength.X * 1.5 < 0) { offsetBitX = 1; } if (inImagePosition.Y - marginLength.Y / 2 >= soleImageResolution.Y || inImagePosition.Y - marginLength.Y * 1.5 < 0) { offsetBitY = 1; } inImagePosition.X = inImagePosition.X % soleImageResolutionWithMargins.X; //probably not needed inImagePosition.Y = inImagePosition.Y % soleImageResolutionWithMargins.Y; var strokePixel = imageWithId.GetPixel(x, y); byte newGColor = (byte)((strokePixel.G | (offsetBitX << 6)) | offsetBitY << 7); strokePixel = Color.FromArgb(strokePixel.A, strokePixel.R, newGColor, strokePixel.B); if (strokePixel.A > 0) { var layerIndex = 0; var occupancy = occupancyArray[inImagePosition.X, inImagePosition.Y]; if (occupancy != 0) { layerIndex = (occupancy) % _layersCount; } occupancyArray[inImagePosition.X, inImagePosition.Y]++; if (!_configuration.UseSmoothAlpha) { var a = strokePixel.A; if (a > 0) { a = 255; } strokePixel = Color.FromArgb(a, strokePixel.R, strokePixel.G, strokePixel.B); } if (!_configuration.UseDithering) { outImages[layerIndex].SetPixel(inImagePosition.X, inImagePosition.Y, strokePixel); } else { var oldPixel = outImages[layerIndex].GetPixel(inImagePosition.X, inImagePosition.Y); if (_configuration.UseSmoothAlpha) { var oldAlpha = oldPixel.A; var maxAlpha = Mathf.Max(oldAlpha, strokePixel.A); strokePixel = Color.FromArgb(maxAlpha, strokePixel.R, strokePixel.G, strokePixel.B); if (layerIndex != 0) { var layer0Pixel = outImages[0].GetPixel(inImagePosition.X, inImagePosition.Y); var layer0OldAlpha = layer0Pixel.A; if (layer0OldAlpha < strokePixel.A) { var newLayer0Pixel = Color.FromArgb(strokePixel.A, layer0Pixel.R, layer0Pixel.G, layer0Pixel.B); outImages[0].SetPixel(inImagePosition.X, inImagePosition.Y, newLayer0Pixel); } } } var ditheringModuler = Mathf.CeilToInt((float)occupancy / _layersCount) + 1; bool ditherPixelActive = (inImagePosition.X + inImagePosition.Y) % ditheringModuler == 0; if (ditherPixelActive) { outImages[layerIndex].SetPixel(inImagePosition.X, inImagePosition.Y, strokePixel); } else { var updatedOldPixel = Color.FromArgb(strokePixel.A, oldPixel.R, oldPixel.G, oldPixel.B); outImages[layerIndex].SetPixel(inImagePosition.X, inImagePosition.Y, updatedOldPixel); } } } } } } } return(outImages.Cast <Image>().ToList()); }